背景

我于16.12.18辞职,之前有过一年左右的前端工作经验。从12月26号开始到1月9号先后面试了微信,百度,阿里巴巴uc,唯品会以及深圳腾讯等几家公司,特此总结与各位共勉。

微信

由于我已经毕业工作过,所以去微信面试是走的社招。微信社招极其严格,共八轮面试,总体来说我基本上当了一把炮灰。由于腾讯前端又细分为重构和JS,所以微信的面试基本上以JS为主。
微信第一面是笔试,共一个小时,四道编程题:

  • JS手写二分搜索算法
  • 给你一段代码,让你发现其中的问题(考察闭包)
  • 实现一个Lazyman(请自行搜索)
  • 用JS代码求出页面上一个元素的最终的background-color,不考虑IE浏览器,不考虑元素float情况。

前两道题比较基础,只要有JS基础的同学一般都应该没什么问题。第三道题,有些难度,但是我之前曾在网上见过该题,使用队列或者promise都可以。第四道题,看完之后一脸懵逼,想了半天也没明白它考察什么内容。由于时间关系,我直接用了window.getComputedStyle。后来交完之后仔细想想,好像确实有很多情况没考虑到,例如当这个元素的背景色为透明时,它最终的背景色应该为其父元素的背景色。

微信二面是项目经历面,我跟面试官大致介绍下我过去一年做的项目。然后掏出笔记本开始一起看我之前写的代码,面试官觉得我之前做的项目复杂度不太高。然后就问了我其他几个问题:既然你面的是小程序组,那么你了解小程序吗?我说不了解。然后问我是否使用过React,我说没有。面试官不是很满意,但最终让我过了。

微信第三面是前端基础面,面完之后我的人生观发生了改变,我感觉我不配做前端。第一个问题是,请问前端优化的手段有哪些?我心里暗喜,这么简单的问题还问。然后我答将CSS文件放在上面,JS文件放在下面。正准备说下一条时,面试官问为什么这样做?我答JS下载解析时会阻塞DOM树的构建,如果放在上面可能会出现白屏的情况。然后面试官问,有没有可能让JS下载解析不阻塞DOM树构建?我答使用defer或asyn字段。面试官问有什么区别?我答...然后面试官问CSS下载解析会不会阻塞DOM树渲染?我已经开始一身汗了,这个问题我不太确定。然后面试官让我接着说优化手段,我答CSS-sprit或者将小图使用base64内嵌。面试官问我CSS-sprit原理是什么?使用base64虽然会减少请求数,但是会增大文件的大小,以什么为基准去衡量什么时候使用base64?此时我已经泪流满面。然后面试官问我了解HTTPS吗?我说了解。他问,请问HTTPS和HTTP有什么区别?我答HTTPS增加了SSL层。面试官问请画出SSL四次握手过程?此刻已经崩溃,我答不会。然后他问请问SSL握手时有对称加密和非对称加密吗?我答不知道。他问如何优化这一层?我答不知道。然后继续回答优化手段?我答将静态内容推向CDN。然后他问现在CDN不稳,时而工作时而崩溃,我有一个首页如何确保每次都能正常显示该首页?答案是CSS inline。他看了看时间,说那就下一个问题。然后给了我一个柱状图,让我使用html和CSS绘制出来。当时我是用了flex。然后他让我手写一个快排算法,我写了。然后他让我用CSS和JS动画在刚才那个柱状图中表现出快排的整个过程,然后我哭了。其实这个动画是见过的,只不过平时使用的都是canvas。面试结束,我跪了。

整体来言,微信的面试难度还是挺大的。他对每个细节的考察非常仔细,不仅要求你知其然更要让你知其为什么。另外一方面我也意识到了准备的不足。

百度

百度的面试是我最喜欢的,考察的比较全面。百度第一面为基础面,包括HTML/CSS/JS各方面,共50分钟左右,大约30个问题左右:

  • HTML5新特性(新增的标签, API等),如localstorage的用法以及与cookie的区别,如何理解web语义化
  • CSS3新特性,如动画等
  • CSS特性,如position的用法,如何实现居中,bootstrap源代码的理解,盒模型(W3C和IE),flex的使用
  • 前端兼容性处理(CSS hack技术)
  • JS基础,如this用法,new关键字的过程,call与apply的区别,闭包,原型以及JS如何实现继承
  • 前端基础,浏览器缓存,跨域,从输入url到渲染的整个过程,事件(W3C和IE),TCP三次握手过程,如何实现懒加载(跟预加载的区别)

百度二面为基础面+算法+项目经历,持续一个小时。问题如下:

  • 之前有看过你做的一个移动页简历,请问如何实现?我主要是使用REM+Media Query,根据不同尺寸的设备进行不同的font-size设置。然后问我REM和EM的区别,如果父元素的font-size也是采用em表示,那么子元素的font-size怎么计算等。
  • 有没有遇到过margin重叠的现象,如何解决?BFC
  • 常见的清除浮动的方法有哪些?bootstrap是怎么做的?bootstrap是怎么实现grid系统的?
  • 怎么理解JS模块化?有没有使用过webpack?

算法题只有一道:什么是浅复制和深复制?有什么区别?如何实现Object的深复制?

首先我对这个问题进行分析,Object是一个树形结构,所以我采用递归的方法进行复制。面试官随后提问能否通过循环的方法?我思考了一会,回答说循环的关键在于循环条件的设置,我想借助栈作为循环判断的条件,当栈为空时,循环结束。当时我立马反应过来,因为Object子节点的个数不确定,可能入栈出栈会存在一定问题。面试官随后问,还有什么东西没有考虑到吗?我想了下说没有。他提示了下,如果出现环怎么办?我愣了一下说不知道。然后他给我个提示说使用深度优先的方法借助栈并不能解决这个问题,然后让我使用宽度优先试试,将代码发给他。面试结束后我发给了他我的代码,各位可以参考下:

// 深度优先遍历复制, 借助队列
function deepCopy(obj) {
    var newObj = {},
        srcQueue = [obj], srcVisitedQueue = [],
        copyQueue = [newObj], copyVisitedQueue = [];

    while (srcQueue.length > 0) {
        var currentSrcElement = srcQueue.shift(),
            currentCopyElement = copyQueue.shift();

        srcVisitedQueue.push(currentSrcElement);
        copyVisitedQueue.push(currentCopyElement);

        for (var key in currentSrcElement) {
            if (typeof currentCopyElement[key] !== 'object') {
                currentCopyElement[key] = currentSrcElement[key];
            } else {
                // 有环的情况
                var index = srcVisitedQueue.indexOf(currentSrcElement[key]);
                if (index >= 0) {
                    currentCopyElement[key] = copyVisitedQueue[index];
                } else {
                    srcQueue.push(currentSrcElement[key]);
                    currentCopyElement[key] = {};
                    copyQueue.push(currentCopyElement[key]);
                }
            }
        }
    }

    return newObj;
}

// Test case
// 1. 只含有简单类型的Object{a: 1, b:2} => pass
// 2. 简单类型和复杂类型同时存在的情况下的Object => pass:
// var obj1 = {
//     a: 1,
//     b: 2,
//     c: {
//         d: 3,
//         e: {
//             f: 4,
//             g: 5
//         }
//     },
//     h: {
//         i: 6,
//         j: 7
//     }
// };
// 3. 有环的情况下的Object => pass:
// var obj1 = {
//     a: 1,
//     b: 2,
//     c: obj1
// };

然后面试官问了关于我项目经历,之前曾看到你推进过公司的模块化,请问是基于什么背景,你是如何推进的,遇到过什么问题等等。

百度三面就是属于开放性面试。首先面试官跟我讨论了下我二面当中的那道算法题,问我是否解决,环如何解决,然后问是否看过Jquery的源代码怎么进行Object的深复制的?我答看过,是采用递归。他然后问为什么Jquery对环的考虑只判断当前节点是否为根节点?该问题我没回答上来。然后他说现在百度有许多部门,每个部门都有自己的组件库,实现的功能基本相同,但有的用的是原生的JS,有的是使用JQuery,有的是使用React,现在想进行统一,如何解决?我说采用重构,他问了问我重构的思路有哪些。然后他说百度有些项目在线上已经很久了,代码比较陈旧,如果你去重构可能会对线上的版本有冲击,你怎么解决这个问题?我答小幅度重构,然后进行回滚等。然后他问,现在有一个很急的项目,需要一个组件,刚好网上提供的有该组件,你是如何屏蔽该组件与现有项目的差异?我的思路是写一个wrapper屏蔽掉该组件与现有库的差异。然后面试官问,如果引入该组件必须引入一个新的库,如React你该如何选择?引入的话有什么好处坏处?我提供了自己的一些看法。

阿里巴巴UC

UC的面试是最轻松的,以至于我感觉我可能没通过。

UC第一面是一个阿里非常高级的前端工程师,面试大约一小时。首先让我讲了讲我对移动前端的了解?然后我讲了讲移动前端布局,JS方面,性能优化等,大于15分钟。然后他问我如何理解前端工程化?然后我又讲了15分钟等。然后他问我有什么问题吗?我问请问你如何理解前端以及你是如何从pc端转入移动端?他站在黑板上给我讲了20多分钟。包括hybrid技术以及现在流行的RN和Weex,以及阿里现在的业务使用的一些技术以及为什么使用等。第一轮面试结束。

第二轮面试是一个后端的哥们,面试大约30分钟。问了我一些前端优化的方法,以及平常遇到过最大的困难是什么,如何解决。有什么难忘的事等。然后问我有什么问题?我说为什么你不问我前端的基础知识也不问我前端的项目经验?他说没必要,已经了解我的背景了等等,然后带我吃了个饭。

唯品会

唯品会技术面共5轮,考察的非常全面。前两面都是基础面跟百度大概类似。但是它重点问了我web安全的一些知识,xss和csrf。问我如何解决相关的问题?xss的话主要使用转义,csrf的话项目中我主要使用的是jwt(javascript web token)。然后针对jwt细节问了我20多分钟。第三面是一个产品经理面,说虽然是技术但是还是要了解产品才行。问我有没有用过唯品会app,我说没有。然后问我知道唯品会是干什么的吗?我说一家专做特卖的网站。然后给我一个唯品会的页面问我有什么建议,然后我讲了20多分钟。第四面是技术总监,进来之后先把我吊了一顿。说虽然感觉你前端基础各方面比较好,但是唯品会的业务性非常强,我没有任何电商方面的经验等,让我过来从头做起之类的。

腾讯

由于面试的是移动方面的业务,所以主要问的有zepto库的使用,移动端布局,优化,JS的一些基础还有localstorage等。重点还问了一下我是如何在项目中开展测试的(单元测试和e2e测试)。后序面试由于要去深圳总部,所以我推掉了。

总结

针对于前端的面试,还是需要一定的时间去好好梳理,尤其是知识点的细节一定要非常清楚。关于项目经历一定要有一条主线,在这条主线上你做过什么,遇到过什么坑,怎么解决一定要非常清楚等。另外一点算法还是很重要的,推荐大家一本书<<剑指offer>>,面试前我前前后后看过三遍。共勉之!