ES6及新特性相关
文章目录
ES6
let const
ES6 之前只有函数作用域和全局作用域。
var会带来变量提升,声明提升到当前作用域顶部,会造成污染。- 在花括号
{}内部由let关键字声明的函数,才是真正的处于块级作用域内部。 - 不存在变量提升
- 暂时性死区:只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
- 不允许重复声明变量。
解构
数组解构
- 只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值
- 只有当一个数组成员严格等于
=== undefined,解构默认值才会生效
let [x = 1] = [null]; // x: null - 惰性求值,能取到就不会走默认值
function f() { return 'aaa' }; let [x = f()] = [1]; // x: 1 - 默认值可以引用解构赋值的其他变量(从左到右),但该变量必须已经声明。
- 字符串也可以解构,会被转化成类数组解构
对象解构
- 数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
- 对象的解构赋值可以取到继承的属性
- 只有当一个属性严格等于
=== undefined,解构默认值才会生效
函数
- 默认传参的参数变量是默认声明的,所以不能用
let或const再次声明。 length属性可返回没有指定默认值的参数个数。...rest参数也不会计入length属性,...rest需要是最后一个参数。- 如果设置了默认值的参数不是尾参数,那么
length属性也不再计入后面的参数了。
|
|
- 函数的
name属性,返回该函数的函数名。
箭头函数
- 箭头函数没有
arguments,没有constructor,无法被new。 - 函数体内的
this对象,就是定义时所在的对象,而不是使用时所在的对象。 - 不能用
yield命令,无法用作 Generator 函数。
数组
- 扩展运算符可以将字符串转化为数组
- 任何定义了
Iterator接口的对象都可以用扩展运算符转化为数组 - 对于那些没有部署
Iterator接口的类似数组的对象{ length: 3 },扩展运算符无法将其转为真正的数组,但是Array.from可以 Map、Set、Generator使用扩展运算符都可以转化为数组Array.from可以把两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
属性遍历
ES6 一共有 5 种方法遍历属性:
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)Object.keys(obj)返回一个数组,包括对象自身的不含继承的所有可枚举属性(不含 Symbol 属性)的键名。Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。Reflect.ownKeys返回一个数组,包含对象自身的不含继承的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
Set 和 Map
Set 和 Map 中 NaN 和 NaN 相同。.keys()、.values()、.entries() 返回的都是遍历器。
Set
- 去重:不会重复添加
- 遍历顺序是插入顺序
- WeakSet 结构与 Set 类似,但是成员只能是对象,没有
size属性,不能遍历
Map
- 对象键只能是字符串,
Map的key可以是对象,当是对象的时候只要内存地址不一样,就视为两个键;需要严格相等,类型不一样也是两个键 - 遍历顺序是插入顺序
- WeakMap 只接受对象作为键名,没有
size属性,不能遍历
Reflect
- 将 Object 对象的一些明显属于语言内部的方法(比如
Object.defineProperty),放到 Reflect 对象上。 - 让 Object 操作都变成函数行为。某些 Object 操作是命令式,比如
name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。 - Reflect 对象的方法与 Proxy 对象的方法一一对应。不管 Proxy 怎么修改默认行为,总是可以在 Reflect 上获取默认行为。
Proxy
用于修改某些操作的默认行为,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值,对for...in不生效。deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args),需要返回一个对象。
Promise
手写 XHR
|
|
Class
- 构造函数的另一种写法:
class Point {}; typeof Point // "function" - 类的所有方法都定义在类的
prototype属性上面,且都是不可枚举的 - 类必须使用
new调用,否则会报错。普通构造函数不用new也可以调用 - 不存在提升
- 也有
name属性 - 如果在一个方法前,加上
static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。静态方法可以被子类继承,但是不会被实例继承
ES6 module
<script> 设置 type="module" 来引入一个 ES6 模块,会异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script> 标签的 defer 属性,会按照在页面出现的顺序依次执行。
也可以设置 async 属性,但是不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。
|
|
与 CommonJS 的区别
- CommonJS 主要用于服务端。
- CommonJS 输出的是一个值的拷贝,ES6 输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJS 的
require()是同步加载模块,ES6 模块的 import 命令是异步加载,有一个独立的模块依赖的解析阶段。 - ES6 模块的
import命令可以加载 CommonJS 模块,但是只能整体加载,不能只加载单一的输出项。
require 第一次加载脚本时,会执行整个脚本,然后在内存中生成一个对象:
|
|
之后再用到这个模块时,就会到 exports 对象上面取值。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
AMD
- 主要用于浏览器端
- 引用模块的时候,将模块名放在
[]中作为reqiure()的第一参数,如果定义的模块本身也依赖其他模块,那就需要将它们放在[]中作为define()的第一参数 - 依赖前置、提前执行
ES7
Array.prototype.includes
|
|
指数函数中缀表示
|
|
ES8
Object.values Object.entries
|
|
String.prototype.padStart 和 String.prototype.padEnd
- 第一个参数为需要达到的长度,若小于当前字符串则返回字符串本身
- 第二个参数为填充使用的字符串,默认为空格。若比需要填充的空格长,则会被截断。
|
|
Object.getOwnPropertyDescriptors
返回指定对象所有**自身属性(非继承属性)**的描述对象。
|
|
Async 和 Await
ES9
异步迭代器
await 可以和 for...of 一起使用。
|
|
ES10
String.prototype.trimStart 和 String.prototype.trimEnd
去除字符串首尾空格。
Array.prototype.flat 和 Array.prototype.flatMap
数组降维度。
|
|
ES2020
- Optional chaining 可选链操作符:
a?.b?.c,只会验证对象是否为null或undefined,不会对所有 Falsy 值做兼容。 - Nullish coalescing Operator 空值处理:左侧为
undefined或null就返回右边a ?? {}
文章作者 xuyou
上次更新 2021-04-27