前端面试计划(二)ES6v2附加代码
## 01. 你能说说ES6有哪些内容吗?
- let、const- 模板字符串- 解构赋值- 扩展运算符- 字符串的扩展方法(includes, startsWith, endsWith, padStart, padEnd, repeat, replaceAll, trimStart, trimEnd...)- 数组的扩展方法(includes, isArray, from, fill, find, findIndex...)- 箭头函数- 函数的rest参数,函数参数的默认值- Symbol- Reflect- Proxy- Promise- Generator- Map- WeakMap- Set- WeakSet- class- import & export- ...
### Symbol
- Symbol 除了表示独一无二的值- 还具有元编程的能力,比如我们手写 Promise 的时候,如果不定义 Symbol.toStringTag 为 Symbol,那么通过 Object.prototype.toString.call 得到的结果就是 [object Object]- 还可以用于判断某对象是否为某构造器的实例 Symbol.hasInstance,很多人手写 instanceof 的时候都是通过 __proto__ 的方式,这在 ES5 是没问题的,然而在 ES6 是通过 Symbol.hasInstance// 1. Symbol 可以表示一个独一无二的值 let key = "a" const symbol1 = Symbol(key) const symbol2 = Symbol(key) console.log(symbol1 === symbol2) // false // 2. Symbol.for 方法会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中 const symbol3 = Symbol.for(key) const symbol4 = Symbol.for(key) console.log(symbol3 === symbol4) // true // 3. Symbol 的元编程能力(改写语法本身),比如手写 Promise 的时候,定义它的 [Symbol.toStringTag] 为 Promise let obj = { a: "1", [Symbol.toStringTag]: "not Object" } console.log(Object.prototype.toString.call(obj)) // [object not Object] // 4. Symbol.hasInstance 用于判断某对象是否为某构造器的实例 let instance = { [Symbol.hasInstance](value) { return "name" in value } } console.log({name:"zf"} instanceof instance) // true // 5. Symbol.toPrimitive
### Reflect
Reflect 将对象的操作集中起来,可以通过 Reflect. 的方式来使用,比如:- Reflect.ownKeys 可以获取对象的普通属性和Symbol类型的属性,如果不使用 Reflect.ownKeys() ,就要使用 Object.keys() 和 Object.getOwnPropertySymbols 将获取到的普通类型的属性和 Symbol 类型的属性拼接起来- Reflect.has 可以判断一个对象是否存在某个属性,如果不用 Reflect.has 就要使用 key in object// Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法 // Reflect 将对象的操作集中起来,可以通过 Reflect. 的方式来使用 // 01. Reflect.ownKeys 可以获取到对象普通属性和Symbol类型的属性 let obj = { a: 1, [Symbol("b")]: 2 } Reflect.ownKeys(obj).forEach(key => { console.log(key, obj[key]) }) // 02. Reflect.has 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同(for in 会遍历原型链) Object.prototype.x = "x" for (let key in obj) { console.log(key) } console.log("a" in obj, "x" in obj) console.log(Reflect.has(obj, "a"), Reflect.has(obj, "x"))
## 02. 箭头函数和普通函数有什么区别呢?
1. 箭头函数没有自己独立的作用域,即它的 this 指向它定义时的作用域2. 箭头函数没有 prototype 属性3. 箭头函数没有 arguments 和 caller4. 箭头函数不能作为构造函数
## 03. Map 和 WeakMap (Set 和 WeakSet) 的区别?
- WeakMap 的 key 只能是对象- WeakMap 没有 size 属性,没有 clear 方法,不支持遍历- WeakMap 是弱引用// Map 引用的对象被置为 null 后,不会被回收掉,WeakMap 引用的对象被置为 null 后,后续会被清空 class MyTest {} let my = new MyTest() let map = new Map() map.set(my, 1) my = null console.log(map) let my2 = new MyTest() let map2 = new WeakMap() map2.set(my2, 1) my2 = null console.log(map2)
## 04. 各种模块化规范的细节
- CommonJs
CommonJS 主要是 Node.js 使用,通过 require `同步加载`模块,exports 导出内容。在 CommonJS 规范下,每一个 JS 文件都是独立的模块,每个模块都有独立的作用域,模块里的本地变量都是私有的
- AMD(Asynchronous Module Definition)
AMD,即异步模块定义。AMD定义了一套JavaScript模块依赖异步加载标准,用来解决浏览器端模块加载的问题。AMD主要是浏览器端使用,通过 define 定义模块和依赖,require 异步加载模块,推崇依赖前置
- CMD(Common Module Definition)
CMD,即通用模块定义。CMD定义了一套JavaScript模块依赖异步加载标准,用来解决浏览器端模块架子啊的问题。CMD主要是浏览器端使用,通过 define 定义模块和依赖,require 异步加载模块,推崇依赖就近
- UMD(Universal Module Definition)
UMD,即通用模块定义。UMD主要为了解决 CommonJS 和 AMD 规范下的代码不通用的问题,同时还支持将模块挂载到全局,是跨平台的解决方案
- ESM(ECMAScript Module)
ESM,即ESModule。官方模块化规范,现代浏览器支持,通过 import 加载模块,export 导出内容