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 } = 123const { toString: b } = trueconst { 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 } = packageJsonfunction Func({ x = 1, y = 2 } = {}) {}for (let [k, v] of Map) {}const { readFile, writeFile } = require("fs")重点难点
undefinedundefinedundefined和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 - 11 + n的自然对数(Math.log(1 + n)){ prop, method() {} })[]定义键([prop],不能与上同时使用)get/set 函数名(属性的描述对象在get和set上)bound 函数名anonymousenumerablemethod() {})属性遍历
自身、可继承、可枚举、非枚举、Symbolfor-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就是外层代码块的thisthis,因此不能用作构造函数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时,只会存在一个NaN5 !== "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上falseObject操作变成函数行为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()),再用子类构造函数修改thissuper(),内部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.mjsimport命令目前只支持加载本地模块(file:协议),不支持加载远程模块.mjs、.js、.json、node)package.json的main字段指定的脚本index四个后缀名文件(.mjs、.js、.json、node)arguments、exports、module、require、this、__dirname、__filenamerequire(),只能使用import()module.exports转化成export defaultCommonJS输出缓存机制在ESM加载方式下依然有效import命令加载CommonJS模块时,不允许采用按需导入,应使用默认导入或整体导入循环加载
脚本A的执行依赖脚本B,而脚本A的执行又依赖脚本Brequire()首次加载脚本就会执行整个脚本,在内存里生成一个对象缓存下来,二次加载脚本时直接从缓存中获取import命令加载变量不会被缓存,而是成为一个指向被加载模块的引用重点难点
this指向undefined,不应该在顶层代码使用thisexport命令输出的接口与其对应的值是动态绑定关系,即通过该接口可获取模块内部实时的值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、MapString、Array、Set、Map、TypedArray、Arguments、NodeListSymbol.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.iteratorIterator接口的数据结构转为数组yield*后跟一个可遍历的数据结构,会调用其遍历器接口for-of、Array.from()、new Set()、new WeakSet()、new Map()、new WeakMap()、Promise.all()、Promise.race()pendingresolvedrejectednew Promise((resolve, reject) => {})未完成变为成功,在异步操作成功时调用,并将异步操作的结果作为参数传递出去未完成变为失败,在异步操作失败时调用,并将异步操作的错误作为参数传递出去resolved状态和rejected状态的回调函数
resolved时调用rejected时调用(可选)Iterator接口的数据结构fulfilled,最终状态才会变成fulfilledrejected,最终状态就会变成rejectedIterator接口的数据结构new Promise(resolve => resolve()))
then()的对象,执行then()相当于执行此对象的then())resolvedresolvedrejected的Promise对象(等价于new Promise((resolve, reject) => reject()))应用场景
重点难点
pending变为resolved、从pending变为rejectedPromise对象就会立即执行,无法中途取消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命令就暂停执行后面的操作,并将其后表达式的值作为返回对象的valuenext()时,再继续往下执行直到遇到下一个yield命令yield命令就一直运行到Generator函数结束,直到遇到return语句为止并将其后表达式的值作为返回对象的valueGenerator函数没有return语句则返回对象的value为undefinedGenerator函数里执行另一个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命令本身没有返回值,可认为是返回undefinedyield命令表达式为惰性求值,等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替换成awaitasync 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.GroupNameconst time = "2017-09-11"、const regexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/utime.replace(regexp, "$<day>/$<month>/$<year>")Promise对象变为resolved状态才进入下一步行分隔符和段分隔符Object.entries()的逆操作)稳定catch()中的参数可省略Symbol值的描述this
windowglobalselfglobalThisn结尾)
Number.parseInt(),将一个字符串转换成指定进制的BigInt类型重点难点
bigintundefined且不再往下执行)
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::barbar.apply(foo, arguments) => foo::bar(...arguments)沙箱功能,允许隔离代码,防止被隔离的代码拿到全局对象new Realm().globalstatic定义属性,该属性不会被实例继承,只能通过类来调用#定义属性,该属性只能在类内部访问#定义方法,该方法只能在类内部访问@注释或修改类和类方法Iterator接口的数据结构fulfilled,最终状态就会变成fulfilledrejected,最终状态才会变成rejectedthen()指定下一步流程,使用catch()捕获错误await命令(借用await解决模块异步加载的问题)最后送大家一张完整的ES6特性图,记得给我点个赞喔,算是对我的一种鼓励。因为图片实在太大无法上传,请关注IQ前端或扫描文章底部二维码,后台回复ES6,获取高清的ES6全部特性记忆图,助你轻松记住ES6全部特性。
❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更多高质量文章
关注公众号IQ前端,一个专注于CSS/JS开发技巧的前端公众号,更多前端小干货等着你喔
资料免费领取学习资料进群拉你进技术交流群IQ前端,更多CSS/JS开发技巧只在公众号推送