一面采用了视频面试,面试过程如下,重点是考官出题
我主要介绍了自己在上一个实习经历中的前端工作,用到的框架,做的工作内容。
但是我的上一个实习是Java开发,附带一些前端,用到的框架,做的内容也很简单,再加上我的表述不清晰,这个环节草草结束了。
反思:做的东西要学会总结,更要学会表达。
求下面两种情况下container的高度
.container { border: 1px }
.item { height: 10px; margin: 10px;}
.container { border: 1px }
.item { height: 10px; margin: 10px; float: left;}
我回答都是20,错误。
我自己试了一下,第一种情况是30,第二种情况是0。
为了方便观察,我给三个div加了颜色。
<html>
<head>
<title>情况1title>
<style type="text/css">
.container { border: 1px;}
.item { height: 10px; margin: 10px;}
style>
head>
<body>
<div class="container" style="background:blue;">
<div class="item" style="background:red;">div>
<div class="item" style="background:orange;">div>
div>
body>
html>
由图可见,蓝色div的高度是30,也就是说,两个div的margin属性起了作用。
原理:两个竖直方向的盒子相遇时,其竖直方向的距离等于上方盒子的下外边距和下方盒子的上外边距中较大的一个。由于两个div的margin值都是10,所以两个div之间相距10,把外面的div撑到了30。
<html>
<head>
<title>情况2title>
<style type="text/css">
.container { border: 1px solid #333;}
.item { height: 10px; margin: 10px; float: left;}
style>
head>
<body>
<div class="container" style="background:blue;">
<div class="item" style="background:red;border:1px solid #333;">div>
<div class="item" style="background:orange;border:1px solid #113;">div>
div>
body>
html>
为了方便观察,我给三个div加了边框。按F12用开发者工具调试,发现两个div的高是10,但宽都是0,外部的div高度为0。
原理:
- 如果一个容器中有多个子容器,如果给子容器设置了float为left,那么我们就可以把所有子容器看作一个靠左对齐的文本。沿着父容器顶部向左推入容器,如果卡住推不动了,判断当前位置能否全部显示该子容器,如果能则完成,如果不能则往下走继续找空档往里面推入容器,以此类推。这是两个div排列在同一行左边的原因。
- float属性有一个著名的特性:会让父元素的高度塌陷。导致高度塌陷的原因是因为浮动元素脱离了正常的文档流,则div.father认为其没有子元素,所以产生了高度塌陷。这是外面的div高度为0的原因。
参考文章:
- 深入理解css中的margin属性
- CSS 深入理解之 float 浮动
2.算法题
给定一个数组如 [1,23,4,6,4,3],实现一个函数 function foo() {},求数组最大最小值的差。
方法一:遍历查找最大最小值(我直接写的就是这个)。
function foo(array) {
var result = 0;//保存结果
var min = array[0],max = array[0];
if(array.length > 0){
for(var i = 1;i < array.length;i++){
if(array[i]>max)
max = array[i];
if(array[i]<min)
min = array[i];
}
}
result = max - min;
return result;
}
方法二:面试官看了方法一,问有没有简单的方法,我说用JS自带的排序函数。
function foo(array) {
var result = 0;//保存结果
var tmp = array.sort();//排序
result = tmp[array.length-1] - tmp[0];
return result;
}
方法三:面试官最后提到可以用max和min函数。JS的 Math.max(x…) 和 Math.min(x…) 可以求指定数的最大值和最小值。
function foo(array) {
var result = 0;//保存结果
var max = Math.max.apply( Math, array);
var min = Math.min.apply( Math, array);
result = max - min;
return result;
}
3.延迟问题
不改变这两行代码,如何使第二个输出延迟一段时间。
log(1)
log(2)
我回答的是 setTimeout(" ",1000),这样不对,setTimeout最后才执行。
- 第一次事件循环,整段代码作为宏任务进入主线程执行。
- 遇到了 setTimeout ,就会等到过了指定的时间后将回调函数放入到宏任务的任务队列中。
- 整个事件循环完成之后,会去检测微任务的任务队列中是否存在任务,存在就执行。这里没有(微任务比如Promise)
- 接着再到宏任务的任务队列中按顺序取出一个宏任务到栈中让主线程执行,那么在这次循环中的宏任务就是 setTimeout 注册的回调函数。
面试官说用sleep,我说我也想到了,但以为sleep只有后台语言才有,JS没有,所以没说。面试官说JS确实没有,可以参考这种思想,用死循环实现。
while循环的方式,容易造成死循环
function sleep(ms){
var start=Date.now(),expire=start+ms;
while(Date.now()<expire);
return;
}
console.log(1);
sleep(2000);
console.log(2);
4.Event Loop(JS事件循环机制)
下面两种情况的输出情况。
setTimeout(function() {log(1)})
log(2)
//输出:2,1
setTimeout(function() {log(1)}, 0)
log(2)
//输出:2,1
当时回答的是先2后1,回来又试了一下,确实是这样。
浏览器内核有多种线程在工作,其中,JS 引擎线程是单线程工作,负责解析运行 JavaScript 脚本。JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
JavaScript 单线程中的任务分为 同步任务 和 异步任务 。同步任务 console.log(2) 会在调用栈中按照顺序排队等待主线程执行,异步任务 setTimeout 则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中等待主线程执行。
setTimeout(fn,0) 的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。
setTimeout(fn) 不写第二个参数,浏览器自动配置时间,在IE,FireFox中,第一次配可能给个很大的数字,100ms上下,往后会缩小到最小时间间隔,Safari,chrome,opera则多为10ms上下。
参考文章:
- JS浏览器事件循环机制
- setTimeout时间设置为0详细解析
- 你会用setTimeout吗
5.变量提升,作用域
以下三种情况分别输出什么,三者有何不同。
//情况一
log(a);
//情况二
log(a);
var a;
//情况三
log(a);
var a;
function a () {};
我回答输出undefined,其他就不清楚了,面试完自己试了一下。
javascript代码并不是一行一行往下执行的。
javascript执行分为2个步骤: 编译(词法解释/预解释) 和 执行。
第二种情况,var a 发生在编译阶段,var a会被提升到当前作用域的最前面。
log(a);
var a;
//经编译后变成下面的情况
var a;
log(a);
//输出undefined
第一种情况,编译后当前作用域没有变量a,所以报错 Uncaught ReferenceError: a is not defined。
第三种情况,(1)函数声明会被提升,函数表达式不会提升。(2) 当出现同名的函数声明,变量声明的时候, 函数声明会被优先提升,变量声明会被忽略。 (3)如果有同名的函数声明,后面的会覆盖前面的。
log(a);
var a;
function a () {};
//经编译后变成下面的情况
function a () {};
log(a);
//输出ƒ a () {}
参考文章:最通俗易懂的javascript变量提升
6.CSS样式
画一个直径10px的圆形,我不会。然后问,画个正方形,我说给div设置宽和高,他说还有吗,我说display设置成block。
画圆:首先建个div,然后把div的宽高设置同样大小,最后把div的边框弧度设为50%。
<html>
<head>
<style type="text/css">
.circle{
width: 10px;
height: 10px;
border-radius: 50%;
background-color: red;
}
style>
head>
<body>
<div class="circle">
div>
body>
html>
效果:
7.算法题
//快速排序
public void quick(int []num){
if(num.length > 0)
quickSort(num,0,num.length);
}
public void quickSort(int []num,int low,int high){
if(low<high){
int md = getMiddle(num,low,high);分成两部分
quickSort(num,low,md);//排左边
quickSort(num,md+1,high);//排右边
}
}
public int getMiddle(int []num,int low,int high){
int tmp = num[low;//中间
while(low<=high){
while(num[high]>tmp && high>=low)
high--;
num[low] = num[high];//小于tmp的数放在左边
while(num[low]<tmp && high>=low)
low++
num[high]=num[low];//大于tmp的数放在右边
}
num[low] = tmp;//中间数
return low;//中间的位置
}
8.算法题
实现一个函数 function flat (arr) {}
输入arr = [1,2,3, [4, 5, [7, 8, 9]]]
return [1,2,3,4,5,6,7,8,9]
//思想:判断数组的元素是否为数字,递归
function flat(arr){
var array = new Array();
for(var i =0;i<arr.length;i++){
if(arr[i].isNaN()){
var tmp = new Array();
tmp = flat(arr[i]);
array.concat(tmp);
}
else
array.push(arr[i]);
}
return array;
}
三、项目介绍
依然是很简单的项目,面试官问用什么实现数据交互,我说用ajax,面试官问ajax的原理,我又不会。
ajax原理:ajax技术最核心的依赖是浏览器提供的XMLHttpRequest对象,使得浏览器可以发出HTTP请求与接收HTTP响应。
参考文章:Ajax原理一篇就够了
总结:
一面主要考察前端基础和算法能力。
面试官说,我的逻辑思维和算法没问题,但前端基础薄弱,关于前端基础的问题我的回答基本都是错的。他人很好,把每一个知识点都标出来了,不然我都不知道我不会的是啥。
这次面试准备确实不充分,我对前端的知识没有一个整体的把握,平时也很少动手练习,导致对css样式没有直观的理解,以后要多动手,多看别人的经验总结。
下一篇:二面总结