针对面试中出镜率比较高的重难点知识梳理。
相比于第一篇 前端面试必备技巧,本篇文章更贴合今年的面试实际。第一篇比较全面,也比较基础,建议先看一遍上一篇再看本篇会更容易理解。
一、ES6常见用法
关于 ES6(泛指 ECMAScript 2015 及以后的版本)几乎是面试必问的,一般的问法是:“平常会使用 ES6 吗?列举几个 ES6 的用法”。
回答出来三四个就差不多了,但回答的每一个都要弄清楚,有的面试官会延伸着追问。
如果时间充足,还是建议看看 阮一峰的 ES6 入门教程 。
1.1 let 和 const
- let 在块级作用域内有效,不会污染全局变量
- const 一经声明不能改变。注意保证的是它指向的内存地址不能改变,如果是对象或者数组里面的属性或元素可以改变的。
- 存在暂时性死区,不能变量提升。
- 只能先声明再使用,且不能重复声明
1.2 字符模板
用作字符串拼接:你好,${name}
1.3 变量的解构赋值
- let [a,b,c] = [1,2,3]
- 交换变量的值:[a,b] = [b,a]
- 提取 JSON 数据,获取服务器返回数据时有用:let {data, code} = res
- 输入模块的指定方法:
const { SourceMapConsumer, SourceNode } = require("source-map");
- 从函数返回多个值: 返回个数组或对象
1.4 扩展运算符
扩展运算符(spread)是三个点(...
)。
- 复制数组:let arr2 = […arr1]
- 合并数组:[…arr1, …arr2, …arr3]
1.5 Promise
- 成功调用
resolve
,失败调用reject
.then
获取结果,.catch
捕获异常。捕获异常还可通过.then
的第二个参数.finally
无论成功失败都一定会调用- 多个并发的请求,用
Promise.all()
- 只有
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。 - 只要
p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
- 只有
let p = Promise.all([p1,p2,p3])
p.then(([res1, res2,res3]) => {};
Promise 示例:
new Promise(){
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
}.then().catch().finally()
1.6 async await
async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async
函数对 Generator 函数的改进:
- 内置执行器,直接调用即可。Generator 还需要调用
next()
才能执行 - 更好的语义。
async
和await
比*
和yield
更好理解 - 返回值是 Promise
1.7 箭头函数
箭头函数 () => {}
的 this
是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this
就继承了定义函数的对象。this
一旦确定以后不会改变。
普通函数的 this 指向的是调用它的对象。
二、移动端的 H5 兼容性和适配
常用的适配方案是 rem + flex 布局。
2.1 rem 适配
先在应用的入口设置基准字体大小,越早执行越好。如果设计图尺寸宽度是 750,就除以 7.5。具体的值根据实际情况来算。
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
设置完基准字体大小后,通过 SASS 的函数封装一个方法方便使用
@function px2rem($value){
@return $value * 0.02rem
}
使用时直接调用封装好的函数即可,value 传 px 的值,方法会自动转换成 rem。
width: px2rem(100)
2.2 采用 flex 布局
flex 布局推荐 阮一峰的 Flex 布局教程:语法篇
三、Vue 相关问题
一般来说中小公司问框架会多一些,具体是 Vue 还是 React 根据公司所用技术栈而定。因为中小公司技术栈比较统一,很少出现同时用两种甚至三种框架的,且更注重干活的能力,所以框架的使用基本会占面试的一半时间。
大公司反而框架问的少,比较注重基础。他们的逻辑是考察你有没有这个能力,如果能力强用啥框架都能快速上手。
因为我对 React 不太熟,所以就只准备了 Vue 的一些问题。下面几个问题都是面试频率非常高的,一定要弄懂。
有一篇文章对 Vue 总结的比较全,这里也是摘录了几个答案。完整的内容看这里:30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度
3.1 Vue双向绑定原理
如果问框架的话 Vue 肯定会问这个问题,把下面这一段话背下来就好。
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
- 实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
- 实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
- 实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
- 实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
回答完这个问题有的面试官还会延伸问:Vue3 将会用
Proxy
替换Object.defineProperty()
,proxy
有什么优点?
建议把 proxy 相关介绍 看一下,说出几个优点。
3.2 虚拟 Dom 实现原理
这个题的重要性仅次于 Vue 双向绑定原理,建议掌握
虚拟 DOM 的实现原理主要包括以下 3 部分:
- 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
- diff 算法 — 比较两棵虚拟 DOM 树的差异;
- pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
优点:
- 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
- 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
- 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。
缺点:
- 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。
深入剖析:Vue核心之虚拟DOM
https://juejin.im/post/5d36cc575188257aea108a74#heading-14
3.3 路由缓存
使用 <keep-alive>
可缓存路由。
它有 include
和 exclude
两个属性,分别表示包含或排除某些路由,值可以是字符串、数组或者正则表达式。
独有的生命周期方法:activited
,deactivited
3.4 路由跳转,name 和 path 跳转的区别
路由跳转的几种方式
// 字符串
this.$router.push('home')
// 命名的路由
this.$router.push({
name: 'user',
params: {
userId: '123'}
})
//接收参数
this.userId = this.$route.params.userId
// 带查询参数,变成 /user?userId=123
this.$router.push({
path: '/user',
query: {
userId: '123'}
})
//接收
this.userId = this.$route.query.userId;
name 和 path 跳转的区别在于
- name 传参用 params,path 传参用 query。
- 用 name 跳转后参数不会携带到 url 上,用 query 传参参数会携带到 url 上。
3.5 路由守卫
全局前置守卫
注意一定要调用 next();
,否则钩子就不会被 resolved。