ES6常问
# let const var 区别
let const var 区别
- var 存在变量提升, let&const 由于存在暂时性死区, 无法在声明前使用变量
- let,const 都用严格的作用域,也就是说有块级作用域
- 不允许重复声明变量
- var 在全局作用域下声明变量会被挂在到 window 上
let const 区别
- let 声明变量是可以修改,const 不可以修改,但是 const 声明的是一个引用类型的话,只是不能修改他的引用地址,这个引用类型的值是可以修改的
- const 声明要赋值,let 声明可以不赋值
# 箭头函数与普通函数的区别
- 箭头函数没有
arguments
对象,可以用...rest 参数获取实参 - 箭头函数不能当做构造函数
- 箭头函数
this
指向问题 - 不能使用 call,apply,bind 方法
# es6 你常用的特性
- 变量的解构赋值
- 数组方法
- class
- module
- promise
- async,await
- 箭头函数
- 模板字符串
- 扩展运算符
- 新增symbol类型 表示独一无二的值,用来定义独一无二的对象属性名
# set,map,WeakSet,WeakMap
Map 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。
- 方法:map.set(key, value);map.get(key);map.has(key);map.delete(key);map.clear();map.size
- Map 迭代: map.keys() map.values() map.entries()for..of 在默认情况下使用的就是这个
Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。
- 方法:map.add(value);map.has(value);map.delete(value);map.clear();map.size
- Map 迭代: 和Map一样
WeakMap: WeakMap 和 Map 的第一个不同点就是,WeakMap 的键必须是对象。
- 方法:weakMap.set(key, value);weakMap.get(key);weakMap.has(key);weakMap.delete(key)
- WeakMap 不支持迭代以及 keys(),values() 和 entries() 方法。所以没有办法获取 WeakMap 的所有键或值。
- WeakSet存放的对象不会计入到对象的引用技术, 因此不会影响GC的回收
WeakSet: 与 Set 类似,但是我们只能向 WeakSet 添加对象(而不能是原始值)。
- 方法:map.add(value);map.has(value);map.delete(value)
- Map 迭代: 不支持迭代
- WeakMap键名指向对象不会计入对象的引用数, 因此不会影响GC的回收
# CommonJS 与 ESModule 的区别
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJS 模块的 require() 是同步加载模块,ES6 模块的 import 命令是异步加载,有一个独立的模块依赖的解析阶段。
# defer与async的区别
默认情况下,浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到<script>
标签就会停下来,等到执行完脚本,再继续向下渲染。如果是外部脚本,还必须加入脚本下载的时间。
defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;(渲染完再执行)
async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。(下载完就执行)
# Require/import如何解决循环引用 Webpack是怎么做的
CommonJS: 脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ES6 处理“循环加载”: ES6 模块是动态引用,如果使用import从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。首先,执行a.mjs以后,引擎发现它加载了b.mjs,因此会优先执行b.mjs,然后再执行a.mjs。接着,执行b.mjs的时候,已知它从a.mjs输入了foo接口,这时不会去执行a.mjs,而是认为这个接口已经存在了,继续往下执行。执行到第三行console.log(foo)的时候,才发现这个接口根本没定义,因此报错。
解决这个问题的方法,就是让b.mjs运行的时候,foo已经有定义了。这可以通过将foo写成函数来解决。(函数具有提升作用)
// a.mjs
import {bar} from './b';
console.log('a.mjs');
console.log(bar);
export let foo = 'foo';
// b.mjs
import {foo} from './a';
console.log('b.mjs');
console.log(foo);
export let bar = 'bar';
Webpack是怎么做的: circular-dependency-plugin
切断引用链