DXY
最想去的一家公司,参加过他们的技术分享会,技术氛围早有耳闻。不局限于做商业化的项目,而是会投入精力去做优化流程和提高效率的事情,开发开源工具,或者重构老旧项目等等
在我问到部门工作流程,第一位面试官说了一句话:在确定好技术选型后,怎么爽怎么写。
这不是程序员的高潮吗?!
全程历时将近3小时,是学到最多的一次面试,也是目前以来被虐的最惨的一次。
笔试
首先笔试半小时,有一些常规的题目,涵盖的内容有基本数据类型,去重数组函数,Dom优化方案,行内元素有哪些,label的作用(这个很有意思),css选择器的查找方式(从右往左);css选择器的优先级;setTimeout异步流程;函数this的指向。
也有一些个人不太确定答案的题目。其中不熟练的点有正则的声明,即时函数的执行流程,操作符优先级,css伪类选择器的优先级
将不确定的题目罗列一下
<!--关于正则 -->
正则声明的正确选项
<!--console输出结果是什么,考察操作符优先级-->
var a = 1,b =2;
console.log(a+++b)
<!--console输出结果是什么,考察即时函数的执行流程-->
var result = (function(){
return 1;
},function(){
return "2"
})()
console.log(typeof result)
<!--关于css选择器优先级排序-->
id class 标签选择器 属性值选择器 伪类选择器 通配符选择器 继承选择(大概是这几类的排序)
做完题目检查了一遍,然后交给hr,等待通知。
等的时候对于DOM创建的优化那一题突然有了更好的方案
题目是这样的:
<!--对下列方法进行优化-->
var nodeI,m;
var data = [] //这里的data是一组真实数据
for(var i = 0,m = data.length ; i<m ; i++){
nodeI = document.creatElement("li");
nodeI.noteText = data[i];
var con = document.getElementById("container");
con.appendChild(nodeI);
}
我在写的时候思考了一会儿,最后只是把container容器的变量提取为了全局,这样就不需要循环都去创建一个变量。
但是之后想到应该使用innerHTML属性直接使用字符串添加,这样的效率是最高的,浏览器只需要对元素重排一次,而不是每次循环都去重新渲染页面一次。
想着想着,面试官就进来了
第一位
一位冷冰冰的大哥,全程没什么话,很认真地在看我带过去的简历,以及笔试题。
第一句话就对我说,你这个基本数据类型写错了吧,这么基础的题
我心想完了不会跪在这种题目吧。拿过来仔细看了下,五种类型string,null,number,boolean,undefined
没写错啊。面试官说还有object
,而Null
是属于object
的。
我觉得他说的不对,于是现场查了下,结果显示我写的应该是对的,我说了句,这点之后再求证好了就跳过了这个话题。
之后,他就开始指了几道我写的答案,问我是怎么思考的。
遇到不会的,我就说我不确定,他也没告诉我正确答案是什么,我说的对不对。一直都是毫无波澜的表情。
过完了题目,我开始想展示下写的项目,拿出资料以及存在手机的动图,他很随意地看了下,然后说好的我知道了。
之后问有没有做过h5,和pc端有什么不同。
我说没有做过完整的项目,h5在一般在手机端使用,点击事件不太一样;另外对页面性能要求比较高
看他反应想来是对我的答案不太满意。
后来问我有没有做过从0开始配置,开发产品,打包项目,到发布上线的完整工作流。
我实话实说没有,因为公司项目不需要使用脚手架,也没有使用打包工具。我自己写的项目有使用过webpack,了解一些配置和打包方法,但没有过发布项目的经验。(后知后觉,他应该是想问开发环境和生产环境的配置有什么不一样)
他说ok了解,然后就问我有没有什么问题问他的
这句话一般就是想要结束面试的标识。我询问了他们对这个岗位的要求,以及他们的技术栈。这些点面试官有比较耐心地去解答,这时候才感觉出来他是个有条不紊,话不多,但是很务实的人。
我感觉应该是看过简历以及笔试题之后,心里已经有了预判觉得水平不够,所以结束的非常快
他也直说,他们组缺乏的成员,我这个水平可能还达不到。让我再等等,他去沟通下有没有其他组的人有兴趣的。
随后就出去了。
第一位失败,重点问题整理如下。
- H5和普通PC端有什么不同
- 从0配置到发布上线的完整流程
- 未来一年对自己的技术方向的规划
- 对前端行业的看法
没有问我的项目,没有问解决问题的过程,没有问笔试题以外的技术问题。
二面
第二位面试官,之前有过一些了解,有关注他的掘金,一个高级前端,端着电脑进来,从头到尾笑眯眯,还是温州老乡。感觉很亲切。偷偷@相学长一下,不知道他会不会知道哈哈哈
too young too simple。我的怀疑人生之路开始了
首先做了简单的自我介绍,在自我介绍里我赶紧趁机讲了下我做过的项目,使用的技术点,以及一些比较有趣的小demo,都是上场面试中没来得及展示的
他有仔细听,有没有评价我也忘了。和上一位面试官一样没有过多的表示。或许是因为对JQ的项目兴趣不大吧。
接着又回到了笔试题上,我就抢先说了应该是错了不少,而且有道题我后来有想到更好的优化方案。
1. 我阐述了我的方案
<!--对下列方法进行优化-->
var nodeI,m;
var data = [] //这里的data是一组真实数据
var html = "";
var con = document.getElementById("container");
for(var i = 0,m = data.length ; i<m ; i++){
html += "<li>"+data[i]+"</li>"
}
con.innerHTML = html;
问1:为什么这样更好呢。
我说只在最后一步把内容加到页面中,减少了浏览器重排重绘的次数
他立刻问2:什么是重排重绘?
前两天刚看到了这个概念,讲了下自己的理解。重排是需要重新分析页面元素尺寸;重绘是元素样式的改变
问3:什么情况下会导致重排重绘?
我说页面布局被修改或者重新渲染的时候。
问4:能不能再具体点
当时没理get到他想要的答案,我就又重复了一遍。他应该是想问怎样算是布局被修改吧
标准答案:
- 添加或者删除可见的DOM元素
- 元素位置改变
- 元素尺寸改变
- 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
- 页面渲染初始化(这个无法避免)
- 浏览器窗口尺寸改变
问5:v-show元素的显示和隐藏算是重排吗?
我说算。我的答案应该是对的,但他应该是希望我能答出“添加或者删除可见的dom元素属于重排”这句话,v-show是设置了css的属性,是算重排的
接着基本上开始一道道过笔试题,以及在原来题目基础上扩展。
2. setTimeout的异步执行
原题如下
<!--执行结果是什么-->
var a = 2;
setTimeout(function(){
a--;
});
a++
console.log(a);
题目还是比较简单,最终输出的是3.
变态的来了
问1:如果外面的a++循环一百万次呢,顺序如何?
答,还是一样,setTimeout在后面
问2:为什么会这样?
(标准答案:同步会阻塞进程。)
这里稍微有点答非所问了,我受到近期看的一篇文章影响一直在强调同步异步和阻塞非阻塞的区别,异步是执行完了告诉你,同步是等待你执行完;堵塞是浏览器一直在请求是否完成。我也不知道我在说啥,我估计他也不知道我在说啥 - -)
问3:知道promise吗,写了一个promise对象,混合setTimeout方法,要求判断输出的先后顺序
知道一点,曾经看到过类似的题目,但是时间比较久了不太记得,被我蒙对了
问4:为什么会这样?
根据我的理解简单讲了下事件循环机制
更多可以参照这两篇文章:
问6:给你一个需求让你写吧。有一个实时搜索的搜索框,连续输入的时候不触发实时搜索,当用户停下来1s以上时,再显示搜索结果
电脑一摆,让我敲。
十脸懵逼说的就是我
不过其实这个需求不应该写不出来,之前做过的导航优化用的也是这个方法,在规定时间内未执行事件,就使用clearTimeout清空计时器。不过当时死脑筋陷入了时间戳,没往这方面想。
正确写法
var time = null;
input.addEventListener("input",()=>{
cleartimeout(time);
time = setTimeout(()=>{
seach();
})
})
学长说如果这只是开始,如果能答出来还可以接着问抽象,不过我第一步就没答出来
泪奔~~~~
3. 对this的理解
原题是让选择正确的调用方法,也比较简单,正确选项长这样
var opt = {
name:"Amy",
say:function(){return this.name}
}
扩展开始
问1:怎么理解函数中的this
指向调用函数的对象
问2:箭头函数的this呢
额。不改变this指向,函数外部指向哪里就是哪里
问3:setTimeout函数里面的呢
指向全局
问4:我把上面的增加一个name2:this.name
输出什么?
undefined..(更确切地说,根据执行环境不同,输出结果也不同。这里的this指向全局,浏览器中的window.name其实是存在的,一般来说是空字符串)
我把say方法改成这样会如何
say:function(){
setTimeout(function(){return this.name})
}
问5:改成这样呢
say:function(){
setTimeout(()=>{return this.name})
}
只能说一定要自信,虽然对于this是理解的,但是问到后面我已经没底气了,都不太敢说。
最后两个问题我都忘了自己当时怎么说的了,正确答案都是undefined
,因为在执行say()的时候函数上下文为全局了
4.跨域
原题是让写几个跨域方案
我写了cors,jsonp,window.name
问1:jsonp是怎么实现的
我说通过script标签引入
问2:为什么可以这么用,数据怎么返回的?
我说script标签是可以跨域访问CDN的
标准答案:JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。
问3:window.name的局限
只能在同一窗口,大小2m
问3:知道localstorge和sessionstorge的区别吗
local是关闭窗口还会存在,数据永久保存,除非去清除浏览器缓存,session关闭窗口就清空了了
问4:localstorge和域名有关吗,sessionstorge呢
相同浏览器的条件下,local在同一域名和端口下是可以共享的,而不同页面无法共享session的数据
(注:如果同源,且属于一个窗口下的iframe,session也是共享的)
4. 关于vue
首先问了几个关于vue的基本问题
拓展开始
问1:你觉得vue和JQ相比,有什么优势
我说了维护更方便,以及数据渲染页面的方式使逻辑和页面分离,更加高效
他好像不太满意,又追问了一遍。
我说有两个最大的优势,一个是双向绑定,一个是组件。他点了点头,然后继续问:
问2:vue的双向绑定的原理是什么
我说在改变输入框的属性时实际上是在调用defineProperty
的get和set方法(更专业的说法叫wacher),在方法里面去修改绑定的元素的值。
问3 :虚拟dom有了解吗
知道..不怎么了解
问4:写的时候为什么data不直接返回对象数据,而是要用函数的形式return出结果?
恩....不了解
问56789:啊我已经说了不了解了所以之后的问题已经不知道他在问什么了...
不过他就开始跟我讲虚拟dom的工作原理,然后还时不时问几个问题,你觉得他是怎么做到的?如果是你会怎么实现?
中途扔了一个问题给我,虚拟DOM的是这么检测到代码已经执行完了,然后插入真实的Dom中的。允许我查资料,他去洗手间。
短时间内我也并没有查出什么东西,然后他回来了跟我解释。
大概意思是,vue里面有一个类似于setTimeout的异步机制,在所有同步进程执行完后,执行这个异步操作,作为这段进程结束的标识。
类似于刚刚问的a++一万次,setTimeout依然在最后执行。
恩...不明觉厉
6. 关于js原生
问1:怎么去实现查找元素的find方法?
没见过这种类型的题目,所以想了一会儿,然后弱鸡地说遍历啊...
问2:他说遍历子节点只能遍历一层啊,那子节点的子节点呢?
继续弱鸡地说,递归呀...
问3:还有什么更有效率的方法可以代替遍历?
不知道哎。。
他引导了我半天,才说有方法叫querySelector()知道吗,我说知道的,见过但是没去了解过。
他开始跟我说这个效率是最高的,我问为啥,他说因为底层就不是用js写的,我不明觉厉,表示惊叹。然而心中默默吐槽,你特么不是要我写个方法吗!不能这么开外挂的!
ps:后来特意去查了下,发现他说的不对啊,这个方法的性能还是比不上js原生getElementById的,不过和jq相比,还是快非常多,特意测试了下
//测试代码
console.time('$(".item")');
for (var i = 0; i < 10000; i++) {
$(".item");
}
console.timeEnd('$(".item")');
//$(".item"): 56.569091796875ms
console.time('querySelectorAll');
for (var i = 0; i < 10000; i++) {
document.querySelectorAll(".item");
}
console.timeEnd('querySelectorAll');
//querySelectorAll: 1781ms
console.time('getElementsByClassName');
for (var i = 0; i < 10000; i++) {
document.getElementsByClassName("item");
}
console.timeEnd('getElementsByClassName');
//getElementsByClassName: 54ms
7.关于css:
1. 行内元素怎么设置垂直居中,块级元素呢,举三种方法
我说了四种方法:
- 常用的绝对定位
- flex布局,然而flex布局的属性名记不清了
- 还有display设置为table
- 使用transform或者margin往回移动50%
2. 清除浮动都有哪些方法
说了both-clear和overflow:hidden两种方法
3. nth-of-child和nth-of-type的区别
nth-of-child:查找位置优先
nth-of-type:查找元素优先
4. 怎么实现在两个元素中间有空位时,移到另一个元素依然让其显示
我说可以用css3动画实现。
他问还有没有其他的方法
没答上来,就算是他的解释也没法让我理解,怎么做到对一个元素hover之后去设置另一个元素的display属性??不用js能实现?
5. 怎么实现三角形,为什么会有这种现象?
将元素宽高设为0,然后边框只保留一边,另外三边设为透明。画了个图说明原因。
6. 怎么对三角形设置阴影
我说用filter中的drop-shadow属性,他问为什么,还有什么做法,我想了一下说可以直接再写个三角形放在下面,还可以写个矩形然后旋转下
关于css我觉得答得还可以,包括后来的反馈也是说擅长css。不过也可能因为到最后了面试官懒得再展开了。
8.最后问了平时是怎么学习的
我说看视频,看书
问:看什么书
我说最近看了dom编程艺术和js面向对象
他马上问:继承有哪几种方式
我讲了我理解的两种,我看的那本书中写了十几种继承方式
问:知道class吗
我说知道一些
问:和构造函数有区别吗
有区别,他的属性的是不可枚举的
这部分应该是答得不怎么样了,没有使用过,只不过以前粗略地浏览过一遍文档,估计因为已经面试了很长时间所以也没多做展开。
面试就告一段落。
总结
以上为问题记录,有些问题很简单,篇幅问题就没一一写出来了;还有些问题实在是超出了理解范围,都不知道他在问什么。只能凭借短期记忆复述他的原话,忘了也很无力啊
高级前端的角度就是,你不仅仅要会用,还要知道为什么要这么用。
最后他问了我还有什么想问他的。我当时傻逼地问了我表现怎么样,他说一般,不算好也不算差
其实我更想问他你是怎么学习的,以及对我的发展有什么建议。
当时被问的有些绝望,只想知道自己有没有戏
技术总监
因为已经到了他们的下班时间了,总监就问了2个问题
1. 为什么你们公司还在用JQ(目前部门就我一个人全职写前端实在是没有人手去重构项目啊!)
2. 你觉得自己在技术方面的优势是什么
我只能极力表达自己的学习能力,毕竟工作时间不长,而且面试表现也不算太好,同时跟他们的技术栈不符。
但面试时百分之90的问题都是我在工作之余的学习成果,如果局限于公司的业务,很多新的概念我是接触不到的。
最后还是个等通知的结果。只能说这是一个全凭实力说话的地方,不看你工作年限的多少,不看你的性格,也没人想要去了解你的潜力,很现实的投入产出比问题,只看你现在能不能为他们产生价值。
不过没关系,收获很多,继续努力吧嘿~