头条面试
近期参加头条面试,把面试过程整理一遍。
到头条总部,前台给了一份前端面试题,然后就带到小屋去做了。总览了一下整个题目,基础题居多,还有一道算法题。当时也有几道题做得不正确,算法题可以说思路也没有。最后总结也发现头条给的面试题不是很好,一会会在每道题下进行说明。
笔试:基础题1、有CSS实现一个三角箭头,如▶️。
这确实是头条原题,题目中的「 有 」应该为「 用 」。这题之前我在做三角箭头的时候曾经用less去做了一个封装,在【 css secret 】一书中也有怎么实现一个三角箭头,所以一下就想到解决方法。
<div class="arrow"></div> |
.arrow { |
以上是我的答案,这道题我自己写的时候是不断调试,也想到用border来绘三角形,但经过面试官提示,我还是做错了,而正确答案应该是下面的代码段。
<div class="arrow"></div> |
.arrow { |
这题考察css中border的高级应用,对于有实战经验的人来说确实很容易,因为平常我们经常用到一些三角形去做些ui。
这题目对于中高级前端来说应该不是什么问题
笔试:基础题2、请使用CSS切不低于两种方式实现自适应搜索框。
没错,这也的的确确是头条原题。错别字「 切 」应该是「 且 」。并且这道题的意思我是很迷茫的,是用input自适应input里的字还是自适应父级元素。
针对这个问题,我问了面试官,他给出的解释是,一个input框,一个button,根据窗口的大小,button宽度不变,input宽度自适应。有点无语。然后我根据需求写下了下面一种方案,根据position去做的。还有另一种我写的是flex,但我平时很少用flex,对flexbox语法不了解,所以只好坦白。
<div class="wrap"> |
.wrap { |
下面是我自己回家后用flex去做的
<div class="wrap"> |
.wrap { |
发现flex真是简单
这道题考察的是布局,position、flexbox的布局
这道题其实是非常好的题目,但是希望头条能严谨些,把题目说清楚。
笔试:基础题3、请问跨域CORS的http请求和普通的http请求有什么区别,请描述通信过程。
这道题我着实不太清楚,在日常开发中基本没遇见跨域问题,就算是本地开发的跨域问题,也是用nginx来解决的。
我在MDN找到跨域的http控制文档。对跨域的不同也有部分说明。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
这道题考察跨域和http,但是考察的比较深入,对于跨域http了解少之又少,甚至是第一次想到这个问题,跨域的http是说明原理。
笔试:基础题4、JS如何解析字节流。
字节流这个名词很少听到,所以这题我也是不知道,只知道与Blob有关。面试官说是如何把blob转成string。
题目很偏,考察Blob对象。
笔试:基础题5、window.onload和document.onload是同时触发吗?请描述触发过程。
在答题的时候,我一直在想window和document基于谁先存在,然后一想window是一个全局的变量。而document只是挂载在window上面的一个属性。所以我回答的时候是指window.onload先触发的。
这道题面试官也没进行讲解和提示。
但你以为这对了么。too simple~!
我回去自己去试的时候给window.onload和document.onload分别赋值如下:
window.onload = function () { |
你猜输出什么?
输出1,document.onload是不执行的。
然后我换了一个方法
window.onload = function () { |
这回我看到这个方法执行了两边,并且先于window.onload执行,这是为什么?
然后我把document.onreadystatechange改造下,想看看内部发生了什么
document.onreadystatechange = function (state) { |
这回可以看到第一次输出的state是这样的:
第二次输出和第一次基本无差别:
然后我去看MDN文档https://developer.mozilla.org/en-US/docs/Web/Events/readystatechange,发现这个方法被执行的原因是因为document.readyState发生改变。
然后我再改下代码
document.onreadystatechange = function (state) { |
第一次输出 document.readyState interactive
第二次输出 document.readyState complete
在找window.onload的文档的时候,我看到这么一句话(https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalEventHandlers/onload)
在文档装载完成后会触发 load 事件。此时,在文档中的所有对象都在DOM中,所有图片,脚本,链接以及子框都完成了装载。
所以这道题很好解释了,window.onload触发,而document不触发,当document.onreadystatechange触发后,完成DOM的渲染才进行window.onload的触发。
也就是说当DOM结构完成渲染后,整个window窗口才完成渲染,执行onload函数。
这道题再拓展一下,假如在document.readyState === 'interactive'时候进行DOM操作是怎么样的?
document.onreadystatechange = function (state) { |
在chrome浏览器下,正常执行:
显然,chrome是不允许document在”interactive”状态添加DOM
接着我再做一个实验,在document.readyState === 'complete'中进行DOM插入会怎么样?
document.onreadystatechange = function (state) { |
一样的结果:
这道题主要是考察浏览器渲染过程,然鹅不知道为什么头条给出了window.onload和document.onload的对比。而不是window.onload和wdocument.onreadystatechange的对比。纳闷
笔试:简单题1、什么是闭包,如何将下面代码每隔1秒输出数组中的数字。
function fun (arr) { |
首先说闭包,我简单在纸上写了 闭包就是在作用域里产生一个新的作用域
然鹅,真正的答案并不是这样,这样描述是错的。我们定义闭包的含义就是 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用 域之外执行。
然后看了下代码,我对题目犹豫了,因为这题输出的就是每隔一秒输出数组的索引(要认真看题!!!),我以为改变的是匿名函数的参数,但是在匿名函数就已经在内部的作用域里面产生了一个新的i,所以这里并不会有声明提升的问题。因此正确的答案应该是:
function fun (arr) { |
这题完全被考蒙了。第一,对自己的积累不自信,第二,题目不看清楚。这个题很简单,考察的是作用域和闭包。
笔试:简单题2、如何实现同域跨标签通信?
这道题我也是没回答上,因为我不清楚题目的具体意思。然后我问了下面试官,他说是同域跨iframe,嗯,这样不就很简单么?
postMessage,可以在文档上查到方法。https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
笔试:简单题3、怎么判断一个object是不是数组(array),请说出至少两种。
// es6 |
var isArray = function (obj) { |
回答上call的话会对call和apply做对比。
call和apply都是改变上下文的引用,唯一不同的是参数不同,call第一个参数为要改变上下文的target,而后面的参数是args
apply只有两个参数,第一个参数是和call是一样的,第二个参数则是类数组的arguments
var isArray = function (obj) { |
考察apply和call,this,作用域。这道题还是不错的
笔试:简单题4、请描述for in和for of区别。
这道题我回答的是for in是循环遍历对象的可枚举属性。
而for of 则是使用了Iterator来实现的。
之后面试官还问到Object.keys,我回答说遍历的是可枚举属性,然后用的hasOwnProperty去判断是否存在在自己的原型上。
考察原型、迭代器
编程题:编程题1、请用数组的reduce方法实现ES6中的map方法。
待更新…
编程题:编程题2、Range(1,10,3)返回[1, 4, 7, 10]。Range(‘A’, ‘E’, 2)返回[‘A’, ‘C’, ‘F’]
待更新…


