Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说es6特性及使用场景_前端es6新特性,希望能够帮助你!!!。
作者:JowayYoung
仓库:Github、CodePen
博客:官网、掘金、思否、知乎
公众号:IQ前端
特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系笔者授权
第三次阅读阮一峰老师的《ES6标准入门》了,以前阅读时不细心,很多地方都是一目十行。最近这次阅读都是逐个逐个字来读,发现很多以前都没有注意到的知识点,为了方便记忆和预览全部ES6特性
,所以写下本文。
以下提到的《ES6标准入门》统一使用《ES6》这个名称来代替,而最新的ES6版本也是截止到当前的ES2020
本文的知识点完全是参考或摘录《ES6》里的语句,有部分语句为了方便理解和记忆,进行了相同意思的转义,同时对知识点进行归类划分。为了让大家能集中精力来记住这些特性,全文一句废话和题外话都没有,全部模块以笔记的形式进行书写,如果看得不是很惯建议对照《ES6》的内容来学习。
本文整理出来的笔记都是书中的精华内容,囊括了整个ES6体系
的所有特性,非常方便大家重新认识全部ES6特性
。半小时的阅读就可对ES6
有一个全面的了解,可认为是一本ES6特性小字典
,收藏后可随时查阅。即使看不完也要拉到本文末尾喔,有个大彩蛋,嘻嘻!
ES6是ECMA
为JavaScript
制定的第6个标准版本,相关历史可查看此章节《ES6-ECMAScript6简介》。
标准委员会最终决定,标准在每年6月正式发布并作为当年的正式版本,接下来的时间里就在此版本的基础上进行改动,直到下一年6月草案就自然变成新一年的版本,这样一来就无需以前的版本号,只要用年份标记即可。ECMAscript 2015
是在2015年6月
发布ES6的第一个版本。以此类推,ECMAscript 2016
是ES6的第二个版本、 ECMAscript 2017
是ES6的第三个版本。ES6既是一个历史名词也是一个泛指,含义是5.1版本
以后的JavaScript下一代标准
,目前涵盖了ES2015
、ES2016
、ES2017
、ES2018
、ES2019
、ES2020
。
所以有些文章上提到的ES7
(实质上是ES2016
)、ES8
(实质上是ES2017
)、ES9
(实质上是ES2018
)、ES10
(实质上是ES2019
)、ES11
(实质上是ES2020
),实质上都是一些不规范的概念。从ES1到ES6,每个标准都是花了好几年甚至十多年才制定下来,你一个ES6到ES7,ES7到ES8,才用了一年,按照这样的定义下去,那不是很快就ES20了。用正确的概念来说ES6目前涵盖了ES2015、ES2016、ES2017、ES2018、ES2019、ES2020。
另外,ES6更新的内容主要分为以下几点
作用
function() {}
{}
var命令
在全局代码中执行const命令
和let命令
只能在代码块中执行const命令
声明常量后必须立马赋值let命令
声明变量后可立马赋值或使用时赋值var
、const
、let
、function
、class
、import
重点难点
const命令
和let命令
不存在变量提升const命令
和let命令
声明变量之前,该变量都不可用const [a, b, c, d, e] = "hello"
const { toString: s } = 123
const { toString: b } = true
const { x, y } = { x: 1, y: 2 }
const { x, y = 2 } = { x: 1 }
const { x, y: z } = { x: 1, y: 2 }
Iterator接口
可采用数组形式的解构赋值const [x, y] = [1, 2]
const [x, y = 2] = [1]
function Func([x = 0, y = 1]) {}
function Func({ x = 0, y = 1 } = {}) {}
应用场景
[x, y] = [y, x]
const [x, y, z] = Func()
Func([1, 2])
const { name, version } = packageJson
function Func({ x = 1, y = 2 } = {}) {}
for (let [k, v] of Map) {}
const { readFile, writeFile } = require("fs")
重点难点
undefined
undefined
undefined
和null
无法转为对象,因此无法进行解构大括号包含
表示Unicode字符(\u{0xXX}
或\u{0XXX}
)for-of
遍历字符串String.fromCodePoint()
的逆操作)新字符串
(Unicode正规化)新字符串
重点难点
4个字节储存
的Unicode字符
上0b或0B开头
表示二进制(0bXX
或0BXX
)0o或0O开头
表示二进制(0oXX
或0OXX
)-2^53
)2^53
)正数1
、负数-1
、零0
)e^n - 1
1 + n
的自然对数(Math.log(1 + n)
){ prop, method() {} }
)[]
定义键([prop]
,不能与上同时使用)get/set 函数名
(属性的描述对象在get
和set
上)bound 函数名
anonymous
enumerable
method() {}
)属性遍历
自身
、可继承
、可枚举
、非枚举
、Symbol
for-in
:遍历对象自身可继承可枚举
属性Object.keys()
:返回对象自身可枚举
属性键组成的数组Object.getOwnPropertyNames()
:返回对象自身非Symbol
属性键组成的数组Object.getOwnPropertySymbols()
:返回对象自身Symbol
属性键组成的数组Reflect.ownKeys()
:返回对象自身全部
属性键组成的数组[...arr]
,相当于rest/spread参数
的逆运算)Iterator接口
的数据结构为真正数组,返回新数组
包含length的对象
、Arguments对象
、NodeList对象
String
、Set结构
、Map结构
、Generator函数
undefined
(空位处理规不一,建议避免出现)扩展应用
const arr = [...arr1]
const arr = [...arr1, ...arr2]
arr.push(...arr1)
Math.max.apply(null, [x, y])
=> Math.max(...[x, y])
[..."hello"]
[...Arguments, ...NodeList]
[...String, ...Set, ...Map, ...Generator]
const [x, ...rest/spread] = [1, 2, 3]
Array.from("hello").length
=> [..."hello"].length
重点难点
keys()
、values()
、entries()
返回的遍历器对象,可用for-of
自动遍历或next()
手动遍历function Func(x = 1, y = 2) {}
const
或let
再次声明function Func({ x = 1, y = 2 } = {}) {}
function Func(x = throwMissing()) {}
undefined
,表明此参数可省略:Func(undefined, 1)
Arguments对象
rest/spread参数
空字符串
(ES5)、变量名
(ES6)函数名
(ES5和ES6)bound 函数名
(ES5和ES6)anonymous
(ES5和ES6)() => {}
x => {}
(x, y) => {}
({x, y}) => {}
this
的机制,而是根本没有自己的this
,导致内部的this
就是外层代码块的this
this
,因此不能用作构造函数function f(x) { return g(x); }
箭头函数误区
this
是定义时所在的对象
而不是使用时所在的对象
this
指向固定化,这种特性很有利于封装回调函数构造函数
,因此箭头函数不可使用new命令
yield命令
,因此箭头函数不能用作Generator函数
Arguments对象
,此对象在函数体内不存在(可用rest/spread参数
代替)正则对象
,尾参数为正则修饰符
(返回的正则表达式会忽略原正则表达式的修饰符)match()
、replace()
、search()
、split()
内部调用转为调用RegExp
实例对应的RegExp.prototype[Symbol.方法]
\uFFFF
的Unicode字符
点字符
(.)Unicode表示法
量词
预定义模式
i修饰符
转义
g修饰符
作用类似)u修饰符
y修饰符
重点难点
y修饰符
隐含头部匹配标志^
y修饰符
对match()
只能返回第一个匹配,必须与g修饰符
联用才能返回所有匹配const set = Symbol(str)
Symbol值
(不登记在全局环境)Symbol值
,如存在此参数则返回原有的Symbol值
(先搜索后创建,登记在全局环境)Symbol值
的描述(只能返回Symbol.for()
的key
)Symbol值
的数组instanceof运算符
判断是否为此对象的实例时会调用此方法Array.prototype.concat()
时是否可展开String.prototype.match()
调用时会重新定义match()
的行为String.prototype.replace()
调用时会重新定义replace()
的行为String.prototype.search()
调用时会重新定义search()
的行为String.prototype.split()
调用时会重新定义split()
的行为for-of
时会调用指定的默认遍历器Object.prototype.toString()
调用时其返回值会出现在toString()
返回的字符串之中表示对象的类型with
时哪些属性会被with环境
排除数据类型
Array
、Function
、Date
、RegExp
、Error
)应用场景
for-in
、for-of
、Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回,只能通过Object.getOwnPropertySymbols
返回window
和global
),使用Symbol.for()
来模拟全局的Singleton模式
重点难点
Symbol()
生成一个原始类型的值不是对象,因此Symbol()
前不能使用new命令
Symbol()
参数表示对当前Symbol值
的描述,相同参数的Symbol()
返回值不相等Symbol值
不能与其他类型的值进行运算Symbol值
可通过String()
或toString()
显式转为字符串Symbol值
作为对象属性名时,此属性是公开属性,但不是私有属性Symbol值
作为对象属性名时,只能用方括号运算符([]
)读取,不能用点运算符(.
)读取Symbol值
作为对象属性名时,不会被常规方法遍历得到,可利用此特性为对象定义非私有但又只用于内部的方法
const set = new Set(arr)
Iterator接口
的数据结构应用场景
[...new Set(str)].join("")
[...new Set(arr)]
或Array.from(new Set(arr))
const a = new Set(arr1)
、const b = new Set(arr2)
new Set([...a, ...b])
new Set([...a].filter(v => b.has(v)))
new Set([...a].filter(v => !b.has(v)))
let set = new Set(arr)
set = new Set([...set].map(v => v * 2))
或set = new Set(Array.from(set, v => v * 2))
重点难点
NaN
时,只会存在一个NaN
5 !== "5"
)keys()
和values()
的行为完全一致,entries()
返回的遍历器同时包括键和值且两值相等const set = new WeakSet(arr)
Iterator接口
的数据结构应用场景
WeakSet结构
中的引用就会自动消重点难点
弱引用
,垃圾回收机制不考虑WeakSet结构
对此成员的引用WeakSet结构不可遍历
WeakSet结构
中const set = new Map(arr)
Iterator接口
且每个成员都是一个双元素数组的数据结构重点难点
NaN
作为键时,只会存在一个以NaN
作为键的值Object结构
提供字符串—值
的对应,Map结构
提供值—值
的对应const set = new WeakMap(arr)
Iterator接口
且每个成员都是一个双元素数组的数据结构应用场景
重点难点
弱引用
,垃圾回收机制不考虑WeakMap结构
对此成员键的引用WeakMap结构不可遍历
WeakMap结构
中只是键而不是值
,值依然是正常引用const proxy = new Proxy(target, handler)
{ proxy, revoke }
,通过revoke()取消代理)k in obj
,返回布尔delete obj[k]
,返回布尔Object.defineProperty()
、Object.defineProperties()
,返回布尔for-in
、Object.keys()
、Object.getOwnPropertyNames()
、Object.getOwnPropertySymbols()
,返回数组Object.getOwnPropertyDescriptor()
,返回对象instanceof
、Object.getPrototypeOf()
、Object.prototype.__proto__
、Object.prototype.isPrototypeOf()
、Reflect.getPrototypeOf()
,返回对象Object.setPrototypeOf()
,返回布尔Object.isExtensible()
,返回布尔Object.preventExtensions()
,返回布尔proxy()
、proxy.apply()
、proxy.call()
new proxy()
应用场景
Proxy.revocable()
:不允许直接访问对象,必须通过代理访问,一旦访问结束就收回代理权不允许再次访问get()
:读取未知属性报错、读取数组负数索引的值、封装链式操作、生成DOM嵌套节点set()
:数据绑定(Vue数据绑定实现原理)、确保属性值设置符合要求、防止内部属性被外部读写has()
:隐藏内部属性不被发现、排除不符合属性条件的对象deleteProperty()
:保护内部属性不被删除defineProperty()
:阻止属性被外部定义ownKeys()
:保护内部属性不被遍历重点难点
Proxy
起作用,必须针对实例
进行操作,而不是针对目标对象
进行操作直接通向原对象
不可读写/扩展/配置/枚举
时,使用拦截方法会报错this
指向Proxy代理
Object方法
的默认行为Object.getOwnPropertyNames()
+Object.getOwnPropertySymbols()
)设计目的
Object
属于语言内部的方法
放到Reflect
上false
Object操作
变成函数行为
Proxy
与Reflect
相辅相成废弃方法
Object.defineProperty()
=> Reflect.defineProperty()
Object.getOwnPropertyDescriptor()
=> Reflect.getOwnPropertyDescriptor()
重点难点
Proxy方法
和Reflect方法
一一对应Proxy
和Reflect
联合使用,前者负责拦截赋值操作
,后者负责完成赋值操作
数据绑定:观察者模式
const observerQueue = new Set();
const observe = fn => observerQueue.add(fn);
const observable = obj => new Proxy(obj, {
set(tgt, key, val, receiver) {
const result = Reflect.set(tgt, key, val, receiver);
observerQueue.forEach(v => v());
return result;
}
});
const person = observable({ age: 25, name: "Yajun" });
const print = () => console.log(`${person.name} is ${person.age} years old`);
observe(print);
person.name = "Joway";
prototype
上,可看作构造函数的另一种写法(Class === Class.prototype.constructor
)new命令
生成实例时自动调用this
构造函数的继承
(总是指向父类
)__proto__
)属性方法的继承
(总是指向父类的prototype
)不会被实例继承
,只能通过类来调用static
定义方法,该方法不会被实例继承
,只能通过类来调用(方法中的this
指向类,而不是实例)this
,再将父类的属性方法添加到this
上(Parent.apply(this)
)this
上(调用super()
),再用子类构造函数修改this
super()
,内部this
指向继承的当前子类
(super()
调用后才可在构造函数中使用this
)普通方法
中指向父类的原型对象
,在静态方法
中指向父类
constructor() { super(); }
定义继承父类,没有书写则显示定义
super()
,否则得不到父类的this
super
上调用父类静态属性方法实例的原型
,所有在类中定义的属性方法都会被实例继承
this
指定到自身上(使用Class.hasOwnProperty()
可检测到)Class.__proto__.hasOwnProperty()
可检测到)const Class = class {}
class
后的类名[prop]
* mothod() {}
async mothod() {}
this.mothod = this.mothod.bind(this)
this.mothod = () => this.mothod()
this
指向类最顶层
原生构造函数
重点难点
Object.assign()
可方便地一次向类添加多个方法(Object.assign(Class.prototype, { ... })
)non-enumerable
)this
),可指定返回另一个对象Descriptor对象
上new.target === Class
写出不能独立使用必须继承后才能使用的类this
指向子类实例,通过super
对某个属性赋值,赋值的属性会变成子类实例的属性super
时,必须显式指定是作为函数还是作为对象使用extends
不仅可继承类还可继承原生的构造函数私有属性方法
const name = Symbol("name");
const print = Symbol("print");
class Person {
constructor(age) {
this[name] = "Bruce";
this.age = age;
}
[print]() {
console.log(`${this[name]} is ${this.age} years old`);
}
}
继承混合类
function CopyProperties(target, source) {
for (const key of Reflect.ownKeys(source)) {
if (key !== "constructor" && key !== "prototype" && key !== "name") {
const desc = Object.getOwnPropertyDescriptor(source, key);
Object.defineProperty(target, key, desc);
}
}
}
function MixClass(...mixins) {
class Mix {
constructor() {
for (const mixin of mixins) {
CopyProperties(this, new mixin());
}
}
}
for (const mixin of mixins) {
CopyProperties(Mix, mixin);
CopyProperties(Mix.prototype, mixin.prototype);
}
return Mix;
}
class Student extends MixClass(Person, Kid) {}
export default Person
(导入时可指定模块任意名称,无需知晓内部真实名称)export const name = "Bruce"
export { age, name, sex }
(推荐)export { name as newName }
import Person from "person"
import * as Person from "person"
import { age, name, sex } from "person"
import { name as newName } from "person"
import "person"
import Person, { name } from "person"
export命令
和import命令
结合在一起写成一行,变量实质没有被导入当前模块,相当于对外转发接口,导致当前模块无法直接使用其导入变量
export { default } from "person"
export * from "person"
export { age, name, sex } from "person"
export { name as newName } from "person"
export { name as default } from "person"
export { default as name } from "person"
默认导出
和改名导出
结合使用可使模块具备继承性use strict
)模块方案
加载方式
加载实现
<script>
进行同步或异步加载脚本
<script src=""></script>
<script src="" defer></script>
(顺序加载,渲染完再执行)<script src="" async></script>
(乱序加载,下载完就执行)<script type="module" src=""></script>
(默认是Defer异步加载)CommonJS和ESM的区别
CommonJS
输出值的拷贝
,ESM
输出值的引用
CommonJS
一旦输出一个值,模块内部的变化就影响不到这个值ESM
是动态引用且不会缓存值,模块里的变量绑定其所在的模块,等到脚本真正执行时,再根据这个只读引用到被加载的那个模块里去取值CommonJS
是运行时加载,ESM
是编译时加载
CommonJS
加载模块是对象(即module.exports
),该对象只有在脚本运行完才会生成ESM
加载模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成Node加载
CommonJS
和ESM
互不兼容,目前解决方案是将两者分开,采用各自的加载方案ESM
采用.mjs
后缀文件名
require()
不能加载.mjs文件
,只有import命令
才可加载.mjs文件
.mjs文件
里不能使用require()
,必须使用import命令
加载文件node --experimental-modules file.mjs
import命令
目前只支持加载本地模块(file:协议
),不支持加载远程模块.mjs
、.js
、.json
、node
)package.json
的main字段
指定的脚本index
四个后缀名文件(.mjs
、.js
、.json
、node
)arguments
、exports
、module
、require
、this
、__dirname
、__filename
require()
,只能使用import()
module.exports
转化成export default
CommonJS
输出缓存机制在ESM
加载方式下依然有效import命令
加载CommonJS模块
时,不允许采用按需导入
,应使用默认导入
或整体导入
循环加载
脚本A
的执行依赖脚本B
,而脚本A
的执行又依赖脚本B
require()
首次加载脚本就会执行整个脚本,在内存里生成一个对象缓存下来,二次加载脚本时直接从缓存中获取import命令
加载变量不会被缓存,而是成为一个指向被加载模块的引用重点难点
this
指向undefined
,不应该在顶层代码使用this
export命令
输出的接口与其对应的值是动态绑定关系
,即通过该接口可获取模块内部实时的值import命令
大括号里的变量名必须与被导入模块对外接口的名称相同import命令
输入的变量只读(本质是输入接口),不允许在加载模块的脚本里改写接口import命令
命令具有提升效果,会提升到整个模块的头部,首先执行import语句
,只会执行一次export default
命令只能使用一次export default命令
导出的整体模块,在执行import命令
时其后不能跟大括号
export default命令
本质是输出一个名为default
的变量,后面不能跟变量声明语句
export default命令
本质是将后面的值赋给名为default
的变量,可直接将值写在其后export default命令
和export {}命令
可同时存在,对应复合导入
export命令
和import命令
可出现在模块任何位置,只要处于模块顶层即可,不能处于块级作用域import()
加载模块成功后,此模块会作为一个对象,当作then()
的参数,可使用对象解构赋值
来获取输出接口Promise.all()
和import()
相结合来实现import()
和结合async/await
来书写同步操作的代码单例模式:跨模块常量
// 常量跨文件共享
// person.js
const NAME = "Bruce";
const AGE = 25;
const SEX = "male";
export { AGE, NAME, SEX };
// file1.js
import { AGE } from "person";
console.log(AGE);
// file2.js
import { AGE, NAME, SEX } from "person";
console.log(AGE, NAME, SEX);
默认导入互换整体导入
import Person from "person";
console.log(Person.AGE);
import * as Person from "person";
console.log(Person.default.AGE);
next()
指向下一个成员,直接到结束位置(数据结构只要部署Iterator接口
就可完成遍历操作)for-of
,Iterator接口
主要供for-of
消费for-of
(自动去寻找Iterator接口)Array
、Object
、Set
、Map
String
、Array
、Set
、Map
、TypedArray
、Arguments
、NodeList
Symbol.iterator
(具备此属性被认为可遍历的iterable
){ done, value }
(必须部署)for-of
提前退出调用,返回{ done: true }
Generator函数
使用ForOf循环
Iterator接口
产生遍历器对象(for-of
内部调用数据结构的Symbol.iterator()
)for-in
获取索引
,for-of
获取值
(可识别32位UTF-16字符)for-in
获取索引
,for-of
获取值
for-in
获取键
,for-of
需自行部署for-of
获取值
=> for (const v of set)
for-of
获取键值对
=> for (const [k, v] of map)
包含length的对象
、Arguments对象
、NodeList对象
(无Iterator接口的类数组
可用Array.from()
转换)Array
、Set
、Map
for-in
区别
for-in
一样的简洁语法,但没有for-in
那些缺点、forEach()
,它可与break
、continue
和return
配合使用应用场景
Iterator接口
的数据结构的Symbol.iterator
Iterator接口
的数据结构转为数组yield*
后跟一个可遍历的数据结构,会调用其遍历器接口for-of
、Array.from()
、new Set()
、new WeakSet()
、new Map()
、new WeakMap()
、Promise.all()
、Promise.race()
pending
resolved
rejected
new Promise((resolve, reject) => {})
未完成
变为成功
,在异步操作成功时调用,并将异步操作的结果作为参数传递出去未完成
变为失败
,在异步操作失败时调用,并将异步操作的错误作为参数传递出去resolved状态
和rejected状态
的回调函数
resolved
时调用rejected
时调用(可选)Iterator接口
的数据结构fulfilled
,最终状态才会变成fulfilled
rejected
,最终状态就会变成rejected
Iterator接口
的数据结构new Promise(resolve => resolve())
)
then()
的对象,执行then()
相当于执行此对象的then()
)resolved
resolved
rejected
的Promise对象(等价于new Promise((resolve, reject) => reject())
)应用场景
重点难点
pending
变为resolved
、从pending
变为rejected
Promise对象
就会立即执行,无法中途取消pending
时,无法得知目前进展到哪一个阶段resolved
或rejected
时,会触发then()
绑定的回调函数resolve()
和reject()
的执行总是晚于本轮循环的同步任务then()
返回新实例,其后可再调用另一个then()
then()
运行中抛出错误会被catch()
捕获reject()
的作用等同于抛出错误resolved
时,再抛出错误是无效的,不会被捕获,等于没有抛出冒泡
性质,会一直向后传递直到被捕获为止,错误总是会被下一个catch()
捕获then()
里定义rejected
状态的回调函数(不使用其第二参数)catch()
捕获错误,不要使用then()
第二个参数捕获catch()
捕获错误,实例抛错不会传递到外层代码,即不会有任何反应
catch()
,一旦被rejected
并不会触发Promise.all()
的catch()
Promise.reject()
的参数会原封不动地作为rejected
的理由,变成后续方法的参数Generator函数
(该函数不执行)返回指向内部状态的指针对象(不是运行结果)function* Func() {}
{ done, value }
(入参会被当作上一个yield命令表达式
的返回值)Generator函数
,返回{ done: true, value: 入参 }
Generator函数
体外抛出错误,在Generator函数
体内捕获错误,返回自定义的new Errow()
return
声明结束返回的值)
yield命令
就暂停执行后面的操作,并将其后表达式的值作为返回对象的value
next()
时,再继续往下执行直到遇到下一个yield命令
yield命令
就一直运行到Generator函数
结束,直到遇到return语句
为止并将其后表达式的值作为返回对象的value
Generator函数
没有return语句
则返回对象的value
为undefined
Generator函数
里执行另一个Generator函数
(后随具有Iterator接口
的数据结构)for-of
自动调用next()
const obj = { method: function*() {} }
const obj = { * method() {} }
上下文环境
一旦遇到yield命令
就会暂时退出堆栈(但并不消失),所有变量和对象会冻结在当前状态
,等到对它执行next()
时,这个上下文环境
又会重新加入调用栈,冻结的变量和对象恢复执行方法异同
next()
、throw()
、return()
本质上是同一件事,作用都是让函数恢复执行且使用不同的语句替换yield命令
yield命令
替换成一个值
yield命令
替换成一个return语句
yield命令
替换成一个throw语句
应用场景
Generator函数
赋值给对象的Symbol.iterator
,从而使该对象具有Iterator接口
重点难点
next()
,指针就从函数头部
或上次停下的位置
开始执行,直到遇到下一个yield命令
或return语句
为止yield命令
,但会变成单纯的暂缓执行函数
(还是需要next()
触发)yield命令
是暂停执行的标记,next()
是恢复执行的操作yield命令
用在另一个表达式中必须放在圆括号
里yield命令
用作函数参数或放在赋值表达式的右边,可不加圆括号
yield命令
本身没有返回值,可认为是返回undefined
yield命令表达式
为惰性求值,等next()
执行到此才求值Symbol.iterator
是此对象本身next()
从外部向内部注入不同的值,从而调整函数行为next()
用来启动遍历器对象,后续才可传递参数next()
时就能输入值,可在函数外面再包一层next()
返回对象的done
为true
,for-of
遍历会中止且不包含该返回对象try-finally
且正在执行try
,那么return()
会导致立刻进入finally
,执行完finally
以后整个函数才会结束try-catch
,throw()
抛错将被外部try-catch
捕获throw()
抛错要被内部捕获,前提是必须至少执行过一次next()
throw()
被捕获以后,会附带执行下一条yield命令
throw()
抛错只可能抛出在函数外部首次next()可传值
function Wrapper(func) {
return function(...args) {
const generator = func(...args);
generator.next();
return generator;
}
}
const print = Wrapper(function*() {
console.log(`First Input: ${yield}`);
return "done";
});
print().next("hello");
Math.pow()
)SharedArrayBuffer
和Atomics
实现,将数据存储在一块共享内存空间中,这些数据可在JS主线程
和web-worker线程
之间共享Generator函数
和自动执行器spawn
包装在一个函数里Generator函数
的*
替换成async
,将yield
替换成await
async function Func() {}
const func = async function() {}
const func = async() => {}
const obj = { async func() {} }
class Cla { async Func() {} }
Thenable对象
:将其等同于Promise对象返回其结果await命令Promise对象
放到try-catch
中(可放多个)Async对Generator改进
应用场景
重点难点
Async函数
返回Promise对象
,可使用then()
添加回调函数return返回值
会成为后续then()
的出参rejected状态
,被catch()
接收到await命令Promise对象
执行完才会发生状态改变,除非遇到return语句
或抛出错误
await命令Promise对象
变为rejected状态
,整个Async函数
都会中断执行await命令Promise对象
放到try-catch
中await命令Promise对象
跟一个catch()
await命令Promise对象
可能变为rejected状态
,最好把其放到try-catch
中await命令Promise对象
若不存在继发关系,最好让它们同时触发await命令
只能用在Async函数
之中,否则会报错forEach()
执行async/await
会失效,可使用for-of
和Promise.all()
代替Async函数
的执行而存在,执行完成就消失undefined
,并且从raw
上可获取原字符串{ ...obj }
,相当于rest/spread参数
的逆运算)扩展应用
const obj = { __proto__: Object.getPrototypeOf(obj1), ...obj1 }
const obj = { ...obj1, ...obj2 }
{ ..."hello" }
{ ...[1, 2] }
const { x, ...rest/spread } = { x: 1, y: 2, z: 3 }
(不能复制继承自原型对象的属性)const obj = { x: 1, ...{ x: 2 } }
.
匹配任意单个字符(dotAll模式
)s修饰符
x
只有在y
后才匹配x
只有不在y
后才匹配Unicode某种属性
的所有字符
\p{PropRule}
\P{PropRule}
\p{...}
和\P{...}
只对Unicode字符
有效,使用时需加上u修饰符
?<GroupName>
)
str.exec().groups.GroupName
const time = "2017-09-11"
、const regexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u
time.replace(regexp, "$<day>/$<month>/$<year>")
Promise对象
变为resolved状态
才进入下一步行分隔符
和段分隔符
Object.entries()
的逆操作)稳定
catch()
中的参数可省略Symbol值
的描述this
window
global
self
globalThis
n
结尾)
Number.parseInt()
,将一个字符串转换成指定进制的BigInt类型重点难点
bigint
undefined
且不再往下执行)
obj?.prop
、obj?.[expr]
func?.(...args)
undefined
或null
,是则使用默认值Promise
)
import命令
被JS引擎静态分析,先于模块内的其他语句执行,无法取代require()
的动态加载功能,提案建议引入import()
来代替require()
require()
是同步加载,import()
是异步加载Iterator接口
的数据结构status
和value
,status
为fulfilled
,value
为返回值status
和reason
,status
为rejected
,value
为错误原因do{}
)throw new Error()
,无需()
或{}
包括_
作为千分位分隔符(增加数值的可读性)?
表示单个参数占位符,...
表示多个参数占位符)f(x)
=> x |> f
)bind
、apply
、call
调用)
bar.bind(foo)
=> foo::bar
bar.apply(foo, arguments)
=> foo::bar(...arguments)
沙箱功能
,允许隔离代码,防止被隔离的代码拿到全局对象new Realm().global
static
定义属性,该属性不会被实例继承
,只能通过类来调用#
定义属性,该属性只能在类内部访问#
定义方法,该方法只能在类内部访问@
注释或修改类和类方法Iterator接口
的数据结构fulfilled
,最终状态就会变成fulfilled
rejected
,最终状态才会变成rejected
then()
指定下一步流程,使用catch()
捕获错误await命令
(借用await
解决模块异步加载的问题)最后送大家一张完整的ES6特性图,记得给我点个赞喔,算是对我的一种鼓励。因为图片实在太大无法上传,请关注IQ前端
或扫描文章底部二维码
,后台回复ES6
,获取高清的ES6全部特性记忆图,助你轻松记住ES6全部特性。
❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更多高质量文章
关注公众号IQ前端
,一个专注于CSS/JS开发技巧的前端公众号,更多前端小干货等着你喔
资料
免费领取学习资料进群
拉你进技术交流群IQ前端
,更多CSS/JS开发技巧只在公众号推送