如何通过前端面试

11,075 阅读19分钟

本教程的目的是教你如何通过(我的)前端面试

本文涵盖了本人日常面试中经常问到的知识点, 面试对象为2~10年工作经验的前端工程师, 我始终认为: 一个合格的前端工程师, 首先应该是一个合格的工程师, 故涉及到的内容不止于前端范畴, 甚至可以说是全栈范畴了, 希望可以给想获得提高的前端工程师一些帮助

本文的重点是列出值得思考的点, 而不是单纯的罗列面试题目, 题目不会直接给出明确的答案, 部分题目本身就是开放性问题, 没有固定答案, 希望大家可以带着思辨性思维去阅读

从上到下是一个大概的优先级顺序, 越靠前的知识点, 面试评价占比越高

1. js基础

js基础问题一般是在整个面试过程中穿插提问, 我个人并不会单独集中提问这里涉及到的问题, 一来这些问题可以在面试沟通的字里行间逐渐感受到候选人的水平, 二来这些问题过于基础, 默认来面试的人都应该已经会了, 重点提问会让对方感觉不被尊重(就像问一个数学系博士一元二次方程解法一样滑稽), 但这并不是说这些知识不那么重要

引用传递

引用传递是js基础中最重要的几个问题之一(如果这种问题不了解那这场面试基本就聊不下去了), 不熟悉引用传递这一特性的开发者会在代码中埋下天坑, 这类隐藏bug很可能在测试阶段蒙混过关, 最终在线上爆发

常规问题是:

  • 什么是引用传递
  • 什么又是传递引用
  • 什么类型有这种行为
  • 什么是包装类型
  • 怎么从内存的角度解释引用问题
  • 什么是深拷贝和浅拷贝
  • 如何实现深拷贝
  • webworker之间传递数据是引用传递吗

事件循环

事件循环无论在浏览器端还是node场景, 都是最基础的问题之一, 这一问题我会重点提问, 对事件循环不理解的开发者可能会写出难以捉摸的bug, 或者滥用事件循环机制带来性能损耗, 我遇到过一个候选人, 他遇到个棘手的问题最终包一层setTimeout 0 就解决了, 但是他自己也不明白为什么(这就很恐怖), 对于这一知识点, 合格的前端开发需要完全明白事件循环的原理, 运作流程, 接触过node开发的还应当知道node与浏览器中事件循环的差异, 对于高级一些的开发者, 则希望其对事件循环的设计做出一些评价, 例如: 为什么要区分microtask和macrotask, 这样设计的目的是什么?

常规问题是:

  • 简述浏览器/node的事件循环机制
  • 什么是 microtask 和 macrotask
  • 浏览器环境下, 渲染dom会插在事件循环的哪一个阶段进行
  • setImmediate 和 setTimeout 的区别
  • Node.js 中 process.nextTick 的运行时机

作用域

作用域是写任何代码都需要考虑清楚的问题, 对作用域不熟悉的人, 往往会使用错误的方式写出运行结果看似正确的代码, 实际上潜藏的很大的隐患, 可能自己写的模块没问题, 但实际上因为作用域的关系影响到了其他的模块却不自知, 作用域的考察不会专门出题(因为没必要而且题目不好设计), 但会夹在其他题目内顺带考察

常规问题是:

  • 什么是变量提升
  • 什么是暂时性死区
  • 什么场景要使用闭包
  • let 与 var 的区别
  • try catch的作用域
  • 什么是词法作用域

基本语法

语法没什么可说的, 需要面试者熟练掌握es6+的新语法特性, 了解新的数据类型(Map, Set, Symbol, WeakMap, WeakSet 等). Promise, Async/Await, 解构赋值, 扩展运算符, 箭头函数这些极其常用的语法需要特别熟练, Generator, Reflect, Proxy, Class, Decorator等语法也要求会用.

常规问题是:

  • == 和 === 的区别
  • 如何实现一个Promise
  • Promise/Async/Await中的错误处理
  • Class中的super方法的作用
  • 箭头函数中的this
  • const定义的对象中的值可以修改吗
  • rest运算符的使用场景
  • Set和数组的性能差异
  • WeakMap/WeakSet分别是什么
  • 如何编写一个Decorator
  • 如何实现一个类似Proxy的功能
  • 什么是Iterator
  • 了解哪些TC39提案中的语法

代码调试

开发者每天都在制造bug, 调试能力是影响开发者工作效率的重要因素, 我面试时会对调试能力有硬性要求, 不会使用调试工具的, 凭意念猜测碰运气调试的选手一定会被挂掉, 正常开发者应当熟练使用chrome dev tool, 并且有严谨的逻辑思维, 知道通过二分法, 控制变量法等方式快速定位问题

常规问题是:

  • 简述js中常见的错误类型
  • 错误堆栈的查看方式
  • 全局错误处理
  • 如何使用断点调试定位问题
  • 如何排查内存泄漏问题
  • 页面白屏时间过长, 如何定位问题
  • 如何断定一个问题是前端问题还是后端问题
  • 描述之前遇到过一个最棘手的bug, 如何解决的

2. 前端框架

当前时间点, 前端框架一般是指 vue/react/angular, 公司的技术栈整体偏向vue, 我面试的时候会稍微偏向提问vue的问题, 当然我本人是保持技术中立的, 面试者如果只会react or angular, 也会对应换成react/angular的问题, 框架相关的面试问题倾向于底层原理, 框架实现的角度(毕竟用谁都会用)

框架使用

这一部分的问题通常是针对经验较少的面试者, 校招, 外包面试或较初级的岗位面试会经常提到, 正常情况下只涉及到vue和react, 国内开发者使用angular的很少, 面试遇到的不多, 这部分问题主要是考察面试者是否能够熟练使用框架开发前端应用, 是否能避免一些显而易见的坑

常规问题是:

  • vue中计算属性的作用
  • vue中$set的作用
  • vue中created与mounted的差异
  • vue如何实现自定义指令
  • vue如何实现一个下拉菜单组件
  • 什么是keep-alive组件
  • vuex使用方法
  • 如何实现模块按需加载
  • 前端路由的常规用法
  • react setState什么时候是同步, 什么时候是异步
  • react shouldComponentUpdate的用法
  • react hoc使用场景
  • redux与vuex的区别
  • 循环渲染中的key有什么作用
  • 数据中没有唯一值字段怎么指定key
  • 如何做性能优化
  • prefetch preload

框架原理

正常的前端开发人员, 只会使用框架肯定是不行的, 如果对框架的原理不了解, 会在不经意间踩到隐藏的坑, 熟悉框架原理也能帮助你更好的优化前端应用, 也可以提升一个人的架构设计思维能力, 前端面试中我会重点考察这一部分的能力, 这里面也会涉及较多开放性问题, 与面试中探讨交流之中我有时可以学到知识, 也可以很快断定一个人的综合能力

常规问题是:

  • vue/react/angular横向对比, 优缺点
  • vue双向绑定实现原理
  • vue依赖收集原理
  • vue中的数组是怎么实现响应式的
  • 虚拟dom与diff算法解决了什么问题
  • vue/react中diff算法的原理, 有什么区别
  • vue nextTick方法是怎么实现的
  • vue template是怎么编译的
  • vue style scope是怎么实现的
  • vue插件机制原理, Vue.use方法的意义
  • vue eventbus传数据是同步还是异步
  • vuex中mutation为什么不推荐处理异步逻辑
  • 前端路由是怎么实现控制页面切换的
  • 当前的diff算法还有什么优化空间
  • 为什么react不需要依赖收集
  • react fiber原理
  • react任务时间分片机制
  • react中的错误边界
  • 什么是数据不可变
  • redux的工作原理
  • mobx如何实现响应式
  • 如何实现一个组件库, 全量引入和按需引入分别怎么实现
  • angular的依赖注入原理
  • rxjs是怎么把事件处理成流的
  • Promise与Observable的区别
  • vue/react/angular当前还存在哪些缺陷, 如何改进

3. 网络通信

前端开发每天都会和网络通信技术打交道, 这部分知识点包括各种网络协议, 浏览器中的一些特殊机制, 比如跨域等, 这些也是很基础的知识点, 任何开发者都必须熟练掌握

网络协议

关于网络协议可以考察的知识点非常多, 通常非计算机专业出身的前端对网络协议这块知识不了解, 推荐阅读 Unix网络编程 这本书来补充知识点. 主要考察内容是http/https, 也会考察一些tcp/udp的知识, 尤其是面试者做过nodejs开发的时候

常规问题是:

  • 描述http通信过程
  • http 302是什么情况下发生的
  • tcp与udp的区别
  • 什么是tcp粘包
  • https是怎么保证通信数据安全的
  • 签发ssl证书的机构起到什么作用
  • http2有什么新特性
  • 什么是多路复用, http1.1可以实现多路复用吗
  • cookie 和 session 有什么区别
  • websocket如何使用
  • 什么是rpc

跨域问题

跨域本身应当属于网络协议的内容, 但前端开发会很频繁遇到这个问题, 所以单独拉出一节来讲, 这也是很重要的基础知识之一, 任何开发者都必须熟悉跨域的出现场景, 如何解决跨域等

常规问题是:

  • 什么是同源策略
  • 常规的跨域解决方案
  • 什么是cors
  • 什么是简单请求/非简单请求
  • 什么是options请求
  • 服务端如何响应options请求
  • 跨域如何发送cookie
  • jsonp的原理
  • 如何通过代理避免跨域

DNS

dns问题在前端面试中不常见, 通常面试者做过服务端开发, 或是面试node职位会重点考察, 对于高级的前端开发人员, 也需要了解其中的一些原理, 来辅助排查或规避问题, 或是找到一些问题的解决方案或优化方案

常规问题是:

  • dns寻址过程
  • 什么是hosts
  • dns变更生效时间
  • 什么是dns prefetch

网络安全

网络安全是个大问题, 很容易产生严重的事故, 但大多数前端人员对此缺乏了解, 一个合格的前端工程师, 应当了解常见的网络安全漏洞, 了解常规攻击手段和对应手段, 能够敏锐的察觉代码中的安全问题

常规问题是:

  • 如何发起csrf攻击, 如何防范
  • 什么是dns劫持
  • 什么是http劫持
  • 如何保证cookie的安全性
  • 如何设计安全的鉴权机制
  • 什么是jwt
  • 什么是OAuth 2.0, 工作流程是怎样的
  • 什么是内容安全策略(CSP)

4. 工程化

工程化能力是现代前端开发很重要的能力之一, 高级前端开发需要有自己搭建前端工程脚手架的能力, 这其中包括了 webpack, babel, eslint, npm等很多相关工具, 这些工具要求熟练使用, 同时懂原理会有很大加分

webpack

webpack周边生态很复杂, 插件繁多, webpack本身功能也多, 想了解原理并不容易, 一般只考察常用的功能的使用, 部分功能最好懂得原理

常规问题是:

  • webpack起到什么作用
  • loader和plugin的区别
  • loader的执行顺序
  • 什么情况下loader可以并行执行
  • 如何编写一个loader or plugin
  • webpack分包加载
  • require和import的模块的差异
  • manifest.json是什么, webpack如何生成manifest.json
  • code splitting 如何实现
  • 什么是 tree shaking
  • hmr运行机制
  • 什么是dev server

babel

babel通常搭配webpack使用, 一般作为webpack loader为前端项目服务, 通常考察常规用法与其中的工作原理

常规问题是:

  • babel如何实现es6 -> es5的转译
  • babel preset是什么
  • 什么是stage 0, stage 2
  • 什么是babel polyfill
  • 为什么需要polyfill
  • babel是如何处理vue template / react jsx 的

eslint

eslint可以考察的内容很少, 一般是搭建工程脚手架使用到, 考察方向偏应用, 不考察原理

常规问题是:

  • 为什么要使用eslint
  • 如何强制约束开发者使用同一套eslint规则
  • eslint如何检查非js代码(例如vue template jsx pug)

npm

npm和前端工作息息相关, 一般是两种用法, 一个是使用依赖包, 一个是开发依赖包, 对于高级的前端开发人员, 我希望他可以理解npm工作原理, 能够自己搭建私有npm仓库, 并基于此制定一系列包的使用规范, 了解npm常见问题, 对于依赖包的管理有一定见解

常规问题是:

  • npm下载的包放在哪里, 如果是依赖的依赖包会放在哪里
  • package-lock文件的作用
  • 全局安装的包放在哪里, 如何查找
  • npm cache机制
  • 什么是npm link
  • 什么是npx
  • 如何开发npm包并上传
  • 如何搭建私有npm
  • 如何管理包的下载
  • 如何检查依赖是否存在漏洞
  • 如何处理循环依赖
  • 什么是peerDependencies

docker

docker是现在最流行的容器引擎, 无论是前端还是后端开发, 都应该对此有一定了解和使用经验, 一个积极主动的前端工程师应当主动探索这些流行的技术能够给前端开发带来什么帮助, 目前主要应用于node服务, 部署开源工具, 持续集成等方面

常规问题是:

  • docker容器之间如何通信
  • 什么是docker-compose
  • 如何清理无用镜像
  • 什么是k8s
  • 如何使用docker打包node服务

Linux

开发工具时会经常与Linux打交道, 开发node服务也会天天登录服务器处理问题, Linux基础是前端工程师必备的能力, 面试中不会重点考察, 但会穿插在其他问题中间接提问, 如果对Linux基本操作不熟悉, 可能会导致前端项目编译时出现问题不知道如何解决, 甚至一些基本的软件安装, 环境配置都搞不定, 更差的情况还会误删文件, 搞坏服务器等

常规问题是:

  • 什么是环境变量
  • Linux中的文件系统
  • 如何检查Linux服务器的负载情况
  • 如何查找服务器上的大文件
  • 磁盘是怎么挂载的
  • 什么是TTY
  • 简述Linux的账户系统
  • 开发命令行工具如何读取命令行参数
  • shell脚本中如何处理字符串, 比如解析json
  • ssh key验证机制

构建发布

这里主要考察自动化构建发布相关知识, 期望开发者可以了解自动化运维的工作流程, 或者可以自行搭建整体的持续集成, 持续交付体系, 但并不要求所有人都会这些, 简历提到必问

常规问题是:

  • 什么是gitlab CI/CD
  • 什么是jenkins
  • 如何实现自动部署脚本
  • 如何实现发布回滚机制
  • 如何设计持续集成流程
  • 如何保证编译服务器每次编译环境都一致
  • 怎样利用缓存加快编译速度

5. 前端相关语言

这部分主要是前端常规的一些预处理器(sass/less) 或者一些js扩展语言 (ts/cs),通常开发者都应该掌握其中几种或全部, 来提升自己的开发效率, 同时也是考察面试者的技术广度和主动学习能力

TS

ts是当前时间点(2019年末), 所有前端程序员都需要会的技能, 如果你还没有开始学习ts, 那你已经落后于时代很多了, 通常我都会询问面试者是否会用ts, 如果是熟悉ts的开发, 我会把ts的熟练程度当做一个重点的加分项

常规问题是:

  • 什么是d.ts, 如何生成它
  • interface和type的区别
  • 枚举的使用方法
  • 什么时候使用类型断言
  • 什么是双重断言
  • 什么是Freshness
  • readonly的使用场景
  • 如何使用泛型
  • 协变与逆变的区别
  • 什么是双向协变
  • 解释类型守卫机制

Scss/Less

css预处理方言很多, 这里一般选最常见的两种考察, 通常情况下会应用即可, 了解底层原理也会有一定加分

常规问题是:

  • Scss/Less的区别
  • mixin的使用场景
  • 使用变量的好处

6. 计算机基础

其实这部分重要性本应该很高的, 排到这里主要是因为前端开发普遍对这块不重视, 不了解, 如果要求过高就会招不到人了, 很无奈只能将它的优先级定在这里. 但对于想要获得自我提升, 有很高追求的前端工程师, 这些也是必须非常非常熟练掌握的技能

数据结构

数据结构这个话题显得有些学院派, 和前端重视应用的场景格格不入, 实际上如果可以非常熟悉数据结构的知识, 可以帮助你写出性能更优的前端应用, 同时也是提升一个人编程思维的重要途径, 我面试中一般会考察这些知识, 并作为很大的加分项

常规问题是:

  • 什么是链表, 双向链表
  • js中的堆和栈分别存储哪些数据
  • 如何实现一个先入先出队列
  • 散列表是怎样的数据结构, 如何实现
  • js中的数组底层是用什么数据结构实现的
  • js中字符串在底层是如何实现的

算法

算法也是很重要但很多人不会的技能, 目前前端面试考察算法的公司也越来越多了, 我面试时也会适当考察几个简单算法题目, 重点是看面试者的思维能力, 分析和解决问题的能力

常规问题是:

  • 排序算法
  • 求一组数中的质数
  • 推算时间复杂度
  • 最小空间复杂度翻转数组
  • 合并链表
  • 前序遍历, 中序遍历, 后序遍历
  • 翻转二叉树
  • 求树的深度
  • 编辑距离
  • 动态规划

编译原理

面试问的不多, 一般是面试者提起或简历有提到才会问, 掌握编译原理的开发者可以通过更多的视角去看待编程问题, 思维也更加缜密理性, 这种面试者会大大加分

常规问题是:

  • 词法分析和语法分析
  • 如何设计文法
  • 解释什么是二义性文法
  • 如何实现自编译
  • 编译时如何做尾递归优化
  • source map的原理
  • js在编译的角度看还存在哪些缺陷

7. 服务端开发

任何一个合格的前端工程师, 他都不应当只是个前端, 掌握一定的服务端开发技能是一个工程师必须做到的, 常规情况下大家学node比较多, 也有一部分前端工程师掌握至少一门服务端开发语言, 通常情况下, 简历提到服务端相关的知识, 我都会详细询问, 这在一定程度上可以体现一个前端面试者的技术广度, 和学习的主动性, 同时了解服务端开发也可以在工作中更顺畅的与其他服务端开发合作, 或者承担一些前端组内工具服务的开发工作

node相关

任何前端工程师至少都应该掌握一些node技能, 无论是使用webpack dev server还是自己开发个人网站, 开发工具, 都有不少的应用场景, 这里有一个误区需要说明, 会写js跑在node上面, 不代表会node开发

常规问题是:

  • node中的模块加载机制
  • stream模块的功能
  • 如何实现node热更新
  • 什么是子进程, 什么场景应该使用子进程, 什么是孤儿进程
  • 父子进程通信
  • 如何实现守护进程
  • pm2的工作原理

微服务

目前各大公司服务端都是微服务的架构, 对微服务有一定了解可以更好的与他人合作, 知识面足够的情况下还能够帮助其他服务端开发优化整体架构设计

常规问题是:

  • 如何设计服务发现机制
  • 什么是领域驱动设计
  • 如何实现负载均衡
  • 什么是幂等
  • 常见的分布式框架

数据库

优秀的前端工程师应该对目前流行的pg mysql mongodb等数据库有一定的了解和实践, 一来可以学习另外一个角度的编程思想, 二来可以理解服务端为什么会和你说"这样格式的数据不好存/不好改", 从而你可以站在更高的角度看待问题, 同时前端团队内部工具的开发往往也会用到这些

常规问题是:

  • 如何设计表结构
  • mysql有哪些存储引擎, 差异是什么
  • 什么时候使用外键
  • 索引的工作原理
  • 多点部署的服务如何保证数据一致性
  • M/S工作原理
  • 如何设计缓存
  • 如何防止缓存雪崩