深入了解最新的 JavaScript 功能(ES7 到 ES13)
深入了解最新的 JavaScript 功能(ES7 到 ES13)
sugar记录一下ES7——ES14的内容
ES7 / ECMAScript 2016
1. 幂运算符
与Math.pow()相同的操作
1 | 2 ** 3 = 8 |
2. Array.prototype.includes()
用于检查数组中是否存在特定值,如果找到匹配项就返回 true
否则返回 false
1 | ['a','b','c'].includes('a'); // true |
3. 函数参数中的尾随逗号
在数组中,我们可以像 [1,2,] 这样使用尾随逗号。 为了保持一致性,现在我们可以在函数参数和参数中使用尾随逗号
1 | const text = (x,y,z,)=>console.log(x,y,z); |
ES8 / ECMAScript 2017
1. 异步函数
我们可以在函数前面添加 async
关键字使其成为异步函数,然后我们可以在函数里面使用 await
关键字
1 | async function test(){ |
2. padStart与padEnd
可以在字符串的开头和结尾添加任意字符用来制作特定长度的字符串
1 | const str = 'hello'; |
3. Object.entries()
允许你将一个对象的可枚举属性转换为一个由 [key, value]
对组成的数组
1 | const obj = { a: 1, b: 2, c: 3 }; |
4. Object.values()
接受一个对象,返回一个数组,该数组仅包含对象内部的值,用逗号分隔
1 | const obj = {name:'JS', lib: 'Angular'}; |
5. Object.getOwnPropertyDescriptors()
接收一个对象,返回指定对象所有自身属性(非继承属性)的描述对象
1 | const obj = { |
6. SharedArrayBuffer
允许 Worker 线程与主线程共享同一块内存。SharedArrayBuffer
的 API 与 ArrayBuffer
一模一样,唯一的区别是后者无法共享数据。
1 | // 主线程 |
上面代码中,postMessage
方法的参数是 SharedArrayBuffer
对象。
Worker 线程从事件的 data
属性上面取到数据。
1 | // Worker 线程 |
共享内存也可以在 Worker 线程创建,发给主线程。
ES9 / ECMAScript 2018
1. 异步遍历器
详细介绍请点击这里
1 | function fetcher(task,time) { |
2. Promise.prototype.finally()
Promise
现在有一个 finally 块,它将在 then
or catch
块之后执行
1 | task().then().catch().finally() |
3. 对象的扩展运算符
...
运算符可以作用在对象上了
1 | // 剩余参数 |
ES10 / ECMAScript 2019
1. Array.prototype.flat()
flat()
方法创建一个新数组,用于将嵌套的数组“拉平”,变成一维的数组。如果没有提供深度,则默认为1。
1 | const nestedArray = [1, [2, [3, 4, [5]]]]; |
2. Array.prototype.flatMap()
flatMap()
方法对原数组的每个成员执行一个函数(相当于执行 Array.prototype.map()
),然后对返回值组成的数组执行 flat()
方法。返回一个新数组,不会影响原数组
1 | // 相当于 [[2, 4], [3, 6], [4, 8]].flat() |
flatMap()
只能展开一层数组。
1 | // 相当于 [[[2]], [[4]], [[6]], [[8]]].flat() |
3. Object.fromEntries()
Object.fromEntries()
方法是 Object.entries()
的逆操作,用于将一个键值对数组转为对象。
1 | Object.fromEntries([ |
4. String.prototype.trimStart()与String.prototype.trimEnd()
它们的行为与 trim()
一致,trimStart()
消除字符串头部的空格,trimEnd()
消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
1 | const s = ' abc '; |
5. Symbol.prototype.description
返回一个字符串,内容为创建 Symbol
时的描述
1 | const sym = Symbol('foo'); |
如果在创建的时候没有提供说明则为 undefined
1 | const sym = Symbol(); |
ES11 / ECMA Script 2020
1. 类的私有变量
通过使用 #
我们现在可以在类中拥有私有变量。
1 | class Person { |
注意,从 Chrome 111 开始,开发者工具里面可以读写私有属性,不会报错,原因是 Chrome 团队认为这样方便调试。### 2. 静态方法与静态属性
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
静态属性指的是 Class 本身的属性,即 Class.propName
,而不是定义在实例对象(this
)上的属性。
1 | class Person { |
3. Promise.allSettled()
用于处理多个 Promise
,与 Promise.all
不同在于 Promise.all
只要有一个 Promise
请求失败它就会报错,而不管其他的请求是否结束,但是 Promise,allSettled
会等待所有的请求都结束哩再返回结果
1 | const promises = [ |
4. 可选链(?.)
用于处理你想要访问嵌套对象的属性或者调用方法时,但不确定属性或者对象是否存在的情况。有助于避免嵌套对象为null
或者undefind
的情况。
1 | const user = { |
5. 空值合并(??)
空值合并运算符 (??
) 在逻辑运算中用于处理 null
或 undefined
的情况。它提供了一种更安全、更方便的方式来为变量提供默认值。
相比于或运算符(||
)来说会更加严格,或运算符是判断是否为假值,而空值合并运算符只会判断是null
或者undefined
1 | const headerText = response.settings.headerText || 'Hello, world!'; |
上面的三行代码都通过||
运算符指定默认值,但是这样写是错的。开发者的原意是,只要属性的值为null
或undefined
,默认值就会生效,但是属性的值如果为空字符串或false
或0
,默认值也会生效
1 | const headerText = response.settings.headerText ?? 'Hello, world!'; |
上面代码中,默认值只有在左侧属性值为null
或undefined
时,才会生效
6. 动态导入
允许你在运行时有条件或按需导入模块,使用 import()
函数实现,该函数返回一个解析为模块命名空间对象的 Promise
1 | mathModulePromise.then((mathModule) => { |
7. BigInt
允许您处理超出标准 Number
类型限制的非常大的整数的数据类型。详细介绍看这里
8. globalThis
globalThis
是一个 JavaScript 全局对象,它提供了在任何环境(包括浏览器和 Node.js)中访问全局对象的标准化方法。具体的全局对象根据 JavaScript 代码运行的上下文而变化:
- 在浏览器环境中,全局对象是
window
。 - 在 Node.js 环境中,全局对象是
global
。
globalThis
提供了跨不同 JavaScript 环境访问全局对象的一致方式,使代码更加可移植并避免特定于环境的代码。
ES12 / ECMA Script 2021
1. String.prototype.replaceAll()
用来替换字符串上所有出现的特定字符串,返回一个新字符串,不会影响原始字符串
1 | const str = 'hello world,hello everyone'; |
2.Promise.any
该方法接受一组 Promise
实例作为参数,包装成一个新的 Promise
实例返回。
只要参数实例有一个变成fulfilled
状态,包装实例就会变成fulfilled
状态。如果所有参数实例都变成rejected
状态,包装实例就会变成rejected
状态。
Promise.any()
跟Promise.race()
方法很像,只有一点不同,就是Promise.any()
不会因为某个 Promise 变成rejected
状态而结束,必须等到所有参数 Promise 变成rejected
状态才会结束。
1 | const promise1 = new Promise((resolve, reject) => { |
3. WeakRef
WeakRef
对象允许你保留对另一个对象的弱引用,而不会阻止被弱引用对象被 GC 回收。WeakRef
的主要用例是通过允许对象在不再使用时进行垃圾收集来避免内存泄漏。
1 | const obj = { data: 'example' }; |
4. &&=
, ||=
跟 ??=
这三个运算符||=
、&&=
、??=
相当于先进行逻辑运算,然后根据运算结果,再视情况进行赋值运算。
1 | // 或赋值运算符 |
它们的一个用途是,为变量或属性设置默认值。
1 | // 老的写法 |
5. 数字分隔符( _ )
允许你在数字文字中使用下划线 ( _ ) 作为分隔符以提高可读性。
1 | const nub = 1_000_000_000; |
ES13 / ECMA Script 2022
1. 顶层 await
它允许你在模块的顶级使用 await
关键字。传统上,await
关键字只能在 async
函数内使用,但对于顶级 await
,你可以直接在模块的顶层使用它。具体的详细列子建议看这里
2. at()
它允许你访问String
中指定索引处的字符或Array
中指定索引处的元素。at()
的主要功能在于它支持负索引,从而更容易从String
或者Array
末尾访问元素。
1 | const str = 'Hello, World!'; |
3. Object.hasOwn
JavaScript
对象的属性分成两种:自身的属性和继承的属性。对象实例有一个hasOwnProperty()
方法,可以判断某个属性是否为原生属性。
Object.hasOwn()
可以接受两个参数,第一个是所要判断的对象,第二个是属性名。
1 | const foo = Object.create({ a: 123 }); |
上面示例中,对象foo
的属性a
是继承属性,属性b
是原生属性。Object.hasOwn()
对属性a
返回false
,对属性b
返回true
。
4. 类的字段声明
在 ES2022 之前,类字段只能在构造函数中声明。
1 | class Car { |
ES2022 消除了此限制。现在我们可以编写这样的代码
1 | class Car { |
5. Array.prototype.findLast() 跟 Array.prototype.findLast()
find()
和findIndex()
都是从数组的0号位,依次向后检查。findLast()
和findLastIndex()
,从数组的最后一个成员开始,依次向前检查,其他都保持不变。
1 | const array = [ |
ES14 / ECMAScript 2023
1. toReversed(),toSorted(),toSpliced(),with()
很多数组的传统方法会改变原数组,比如push()
、pop()
、shift()
、unshift()
等等。数组只要调用了这些方法,它的值就变了。而toReversed()
,toSorted()
,toSpliced()
,with()
对数组进行操作时不会改变原数组,而是返回一个原数组的拷贝
Array.prototype.toReversed() -> Array
Array.prototype.toSorted(compareFn) -> Array
Array.prototype.toSpliced(start, deleteCount, ...items) -> Array
Array.prototype.with(index, value) -> Array
它们分别对应数组的原有方法。
toReversed()
对应reverse()
,用来颠倒数组成员的位置。toSorted()
对应sort()
,用来对数组成员排序。toSpliced()
对应splice()
,用来在指定位置,删除指定数量的成员,并插入新成员。with(index, value)
对应splice(index, 1, value)
,用来将指定位置的成员替换为新的值。
1 | const sequence = [1, 2, 3]; |
2. Symbols 可以用作 WeakMap 的key
3. #!
命令
具体看这