最完整的 JavaScript 新功能指南:ES2024 ~ ES2016
ECMAScript与JavaScript
ECMAScript
- 通常看做
JavaScript
的标准化规范 - 实际上
JavaScript
是ECMAScript
的扩展语言,ECMAScript
只提供了最基本的语法,约定了代码该如何编写,只是停留在语言层面。
JavaScript
-
JavaScript
实现了ECMAScript
的语言标准,并在其基础上做了一些扩展。 - 在浏览器中环境中,
JavaScript = ECMAScript + WebApis(BOM + DOM)
- 在
node
环境中,JavaScript = ECMAScript + NodeApis(fs,net等)
- 所以,
JavScript
语言本身指的就是ECMAScript
2015年开始,ES
保持每年一个版本的迭代,ES6
其实等价于 ES2015
,这个 ES2015
代表的是当时发表的年份,ES2016
发布的称为 ES7
,依次类推,ES2023
可以称为 ES14
了,版本改动概览:
ES2024
Well-Formed Unicode Strings
String
原型上新增两个方法isWellFormed
和toWellFormed
isWellFormed()
方法返回一个表示该字符串是否包含单独代理项(developer.mozilla.org/zh-CN/docs/… true
,否则返回 false
。
const strings = [
// 单独的前导代理
"ab\uD800",
"ab\uD800c",
// 单独的后尾代理
"\uDFFFab",
"c\uDFFFab",
// 格式正确
"abc",
"ab\uD83D\uDE04c",
];
for (const str of strings) {
console.log(str.isWellFormed());
}
// 输出:
// false
// false
// false
// false
// true
// true
toWellFormed()
方法返回一个字符串,其中该字符串的所有单独代理项都被替换为 Unicode
替换字符 U+FFFD
。
const strings = [
// 单独的前导代理
"ab\uD800",
"ab\uD800c",
// 单独的后尾代理
"\uDFFFab",
"c\uDFFFab",
// 格式正确
"abc",
"ab\uD83D\uDE04c",
];
for (const str of strings) {
console.log(str.toWellFormed());
}
// Logs:
// "ab�"
// "ab�c"
// "�ab"
// "c�ab"
// "abc"
// "ab????c"
Atomics.waitAsync()
Atomics.waitAsync()
静态方法在共享内存位置异步等待并返回一个Promise。与Atomics.wait()
不同,waitAsync
是非阻塞的,并且可以在主线程上使用。
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);
const result = Atomics.waitAsync(int32, 0, 0, 1000);
// { async: true, value: Promise {<pending>} }
ArrayBuffer.prototype.resizable
resizable
属性是一个访问器属性,其set
访问器函数是未定义的,这意味着您只能读取该属性。该值是在构造数组时建立的。如果在构造函数中设置了maxByteLength
选项,resizable
将返回true;如果不是,它将返回false
。当其为true
时,则可以调整大小:
const buffer1 = new ArrayBuffer(8, { maxByteLength: 16 });
const buffer2 = new ArrayBuffer(8);
console.log(buffer1.resizable);
// Expected output: true
console.log(buffer2.resizable);
// Expected output: false
if (buffer1.resizable) {
console.log("Buffer is resizable!");
buffer.resize(12);
}
ES2023
从数组末尾查找元素
新增两个方法: .findLast()
、.findLastIndex()
从数组的最后一个元素开始查找,可以同 find()
、findIndex()
做一个对比。
const arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];
// find vs findLast
console.log(arr.find(n => n.value % 2 === 1)); // { value: 1 }
console.log(arr.findLast(n => n.value % 2 === 1)); // { value: 3 }
// findIndex vs findLastIndex
console.log(arr.findIndex(n => n.value % 2 === 1)); // 0
console.log(arr.findLastIndex(n => n.value % 2 === 1)); // 2
Hashbang 语法
如下所示,在 index.js
脚本文件里编写 JS 代码,如果要正确的执行,需要在控制台输入 node index.js
。
console.log("JavaScript");
如果直接执行 ./index.js
脚本文件会得到以下报错:
./index.js
./index.js: line 1: syntax error near unexpected token `"JavaScript"'
./index.js: line 1: `console.log("JavaScript");'
很正常,因为我们并没有指定使用何种解释器来执行上述脚本文件。Hashbang
语法是用来指定脚本文件的解释器是什么,语法规则是在脚本文件头部增加一行代码:#!/usr/bin/env node
。
// #!/usr/bin/env node
console.log("JavaScript");
注意,还需修改脚本文件的权限 chmod +x index.js
,否则执行会报 permission denied: ./index.js
错误。
将 Symbols 作为 WeakMap 的键
这允许使用唯一的 Symbols
作为键。目前 WeakMaps
只允许对象作为键。因为它们共享同样的身份特性。
Symbol
是ECMAScript
中唯一的原始类型,允许使用唯一的值,因此可以使用Symbol
作为键,而不是创建一个新的带有WeakMap
的对象。
const weak = new WeakMap();const key = Symbol('my ref');
const someObject = { a:1 };weak.set(key, someObject);
console.log(weak.get(key));
通过复制改变数组
这在 Array.prototype
上提供了额外的方法,通过返回带有更改的新数组副本,而不是更新原始数组来更改数组。
新引入的 Array.prototype
函数包括:
- Array.prototype.toReversed()
- Array.prototype.toSorted(compareFn)
- Array.prototype.toSpliced(start, deleteCount, …items)
- Array.prototype.with(index, value)
const sequence = [1, 2, 3];
sequence.toReversed() // [3, 2, 1]
sequence // [1, 2, 3]
const outOfOrder = [3, 1, 2];
outOfOrder.toSorted() // [1, 2, 3]
outOfOrder // [3, 1, 2]
const array = [1, 2, 3, 4];
array.toSpliced(1, 2, 5, 6, 7) // [1, 5, 6, 7, 4]
array // [1, 2, 3, 4]
const correctionNeeded = [1, 1, 3];
correctionNeeded.with(1, 2) // [1, 2, 3]
correctionNeeded // [1, 1, 3]
ES2022
Class Fields
允许在类最外层声明类成员,参考 github.com/tc39/propos…
class Person {
name = 'Tom'
}
私有化类成员:支持私有实例、私有静态类型字段、私有方法。
class Person {
#privateField1 = 'private field 1'; // 私有字段赋初值
#privateField2; // 默认 undefined
static #privateStaticField3 = 'private static field 3'
constructor(value) {
this.#privateField2 = value; // 实例化时为私有字段赋值
}
#toString() {
console.log(this.#privateField1, this.#privateField2, InstPrivateClass.#privateStaticField3);
}
print() {
this.#toString()
}
}
const p = new Person('private field 2')
p.print()
私有字段检查
使用 in
操作符检测某一实例是否包含要检测的私有字段。
class Person {
#name = 'Ergonomic brand checks for Private Fields';
static check(obj) {
return #name in obj;
}
}
Top-level await
以前 await
必须随着 async
一起出现,只有在 async
函数内才可用。当需要在一些文件顶部进行初始化的场景中使用时就有不支持了,* await
可以解决这个问题,但它仅支持 ES Modules
。
let jQuery;
try {
jQuery = await import('https://cdn-a.com/jQuery');
} catch {
jQuery = await import('https://cdn-b.com/jQuery');
}
正则新增 /d 修饰符
以前的正则表达式支持 3 个修饰符:/i
(忽略大小写)、/g
(全局匹配)、/m
(多行),当执行正则表达式的 exec()
方法时,新增一个 /d
修饰符,它会返回一个 indices
属性,包含了匹配元素的开始、结束位置索引。
const str = 'ECMAScript_JavaScript'
const regexp = /sc/igd // 忽略大小全局匹配并返回匹配元素的开始、结束位置索引
console.log(regexp.exec(str).indices[0]) // [ 4, 6 ]
console.log(regexp.exec(str).indices[0]) // [ 15, 17 ]
// 包含组信息
const text = 'zabbcdef';
const re = /ab+(cd(ef))/d;
const result = re.exec(text);
result.indices; // [ [1, 8], [4, 8], [6, 8] ]
// 具名组匹配
const text = 'zabbcdef';
const re = /ab+(?<Z>cd)/d;
const result = re.exec(text);
result.indices.groups; // { Z: [ 4, 6 ] }
.at() 操作符
根据指定索引获取数组元素,不同的是它支持传递负数,例如 -1 获取最后一个元素。
const arr = ['a', 'b', 'c']
console.log(arr.at(0));
console.log(arr.at(-1)); // 等价于 arr[arr.length - 1]
Object.hasOwn()
Object.hasOwn()
提供了一种更安全的方法来检查对象是否具有自己的属性,适用于检查所有的对象。Object.prototype.hasOwnProperty()
方法遇到 obj = null
这种情况会报错,参见以下示例:
const person = Object.create({ name: 'Tom' })
person.age = 18;
console.log(Object.hasOwn(person, 'name')); // false
console.log(Object.hasOwn(person, 'age')); // true
// 遇到这种情况 hasOwnProperty 会报错
const p1 = null
console.log(p1.hasOwnProperty('name')); // TypeError: Cannot read properties of null (reading 'hasOwnProperty')
Error Cause
Error Cause
是由阿里巴巴提出的一个提案,为 Error 构造函数增加了一个 options
,可设置 cause
的值为任意一个有效的 JavaScript
值。
例如,自定义错误 message
,将错误原因赋给 cause
属性,传递给下一个捕获的地方。
try {
await fetch().catch(err => {
throw new Error('Request failed', { cause: err })
})
} catch (e) {
console.log(e.message);
console.log(e.cause);
}
Class Static Block
类的静态初始化块是在类中为静态成员提供了一个用于做初始化工作的代码块。
class C {
static x = 'x';
static y;
static z;
static {
try {
const obj = doSomethingWith(this.x);
this.y = obj.y;
this.z = obj.z;
} catch (err) {
this.y = 'y is error';
this.z = 'z is error';
}
}
}
ES2021
String.prototype.replaceAll
replaceAll()
用于替换正则表达式或字符串的所有匹配项,之前的 replace()
只会匹配一个。
console.log('JavaScript'.replaceAll('a', 'b')); // JbvbScript
Promise.any
Promise.any()
接收一个 Promise
数组做为参数,返回第一个执行成功的 Promise
,如果全部执行失败将返回一个新的异常类型 AggregateError
,错误信息会以对象数组的形式放入其中。
const delay = (value, ms) => new Promise((resolve, reject) => setTimeout(() => resolve(value), ms));
const promises = [
delay('a', 3000),
delay('b', 2000),
delay('c', 4000),
];
Promise.any(promises)
.then(res => console.log(res)) // b
.catch(err => console.error(err.name, err.message, err.errors)) // 全部失败时返回:AggregateError All promises were rejected [ 'a', 'b', 'c' ]
数字分隔符
数字分隔符可以让大数字看起来也容易理解。
const budget = 1_000_000_000_000;
console.log(budget === 10 ** 12); // true
逻辑赋值运算符
结合了逻辑运算符 &&
、||
、??
和逻辑表达式 =
。
a ||= b;
// 等效于以下两种写法
// a || (a = b); a为falsy时执行右边
// if(!a) a = b;
a &&= b;
// 等效于以下两种写法
// a && (a = b); a为truth时执行右边
// if(a) a = b
a ??= b;
// 等效于以下两种写法
// a ?? (a = b); a为undefined或null时执行右边
// if(a === nudefined || a === null) a = b;
WeakRef
WeakRef
对象包含对对象的弱引用,这个弱引用被称为该 WeakRef
对象的 target
或者是 referent
。对对象的弱引用是指当该对象应该被 GC
回收时不会阻止 GC
的回收行为。而与此相反的,一个普通的引用(默认是强引用)会将与之对应的对象保存在内存中。只有当该对象没有任何的强引用时,JavaScript
引擎 GC
才会销毁该对象并且回收该对象所占的内存空间。
WeakRef()
用来创建一个 WeakRef 对象。
WeakRef.prototype.deref()
返回当前实例的 WeakRef
对象所绑定的 target
对象,如果该 target
对象已被 GC
回收则返回 undefined
。
const obj = { a: 1 };
const ref = new WeakRef(obj)
console.log(ref.deref()); // {a: 1}
ES2020
matchAll - 匹配所有
String.prototype.matchAll()
会返回正则匹配的所有字符串及其位置,相比于 String.prototype.match()
返回的信息更详细。
const str = 'JavaScript'
const regexp = /a/g
console.log([...str.matchAll(regexp)]);
// Output:
[
[ 'a', index: 1, input: 'JavaScript', groups: undefined ],
[ 'a', index: 3, input: 'JavaScript', groups: undefined ]
]
模块新特性
-
import
动态导入
动态导入意思是当你需要该模块时才会进行加载,返回的是一个 Promise
对象。只有在 ES Modules
模块规范下才支持
// index-a.mjs
export default {
hello () {
console.log(`hello JavaScript`);
}
}
// index-b.mjs
import('./index-a.mjs').then(module => {
module.default.hello(); // hello JavaScript
})
import.meta
import.meta
只能在模块内部使用,如果在模块外部使用会报错。
这个属性返回一个对象,该对象的各种属性就是当前运行的脚本的元信息。具体包含哪些属性,标准没有规定,由各个运行环境自行决定。一般来说,import.meta
至少会有下面两个属性。
import.meta.url
返回当前模块的 URL 路径。举例来说,当前模块主文件的路径是 foo.com/main.js,imp… 就返回这个路径。
import.meta.scriptElement
是浏览器特有的元属性,返回加载模块的那个<script>
元素,相当于 document.currentScript
属性。
BigInt
BigInt
是新增的一种描述数据的类型,用来表示任意大的整数。因为原先的 JavaScript Number
类型能够表示的最大整数位 Math.pow(2, 53) - 1
,一旦超出就会出现精度丢失问题。详情可参考这篇大数危机的文章 github.com/qufei1993/b…
9007199254740995 // 会出现精度丢失
9007199254740995n // BigInt 表示方式一
BigInt('9007199254740995') // BigInt 表示方式二
Promise.allSettled
Promise.allSettled()
会等待所有的 Promise
对象都结束后在返回结果。
const delay = (value, ms, isReject) => new Promise((resolve, reject) => setTimeout(() => isReject ? reject(new Error(value)) : resolve(value), ms));
const promises = [
delay('a', 3000),
delay('b', 2000, true),
];
Promise.allSettled(promises)
.then(res => console.log(res))
// Output:
[
{ status: 'fulfilled', value: 'a' },
{
status: 'rejected',
reason: Error: b
at Timeout._onTimeout (/index.js:1:108)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
}
]
全局对象globalThis
JavaScript
可以运行在不同的环境,浏览器为 window
、Node.js
为 global
。为了能够统一全局环境变量,引入了 globalThis
。
window === globalThis // 浏览器环境
global === globalThis // Node.js 环境
for-in 机制
ECMA-262 规范没有规定 for (a in b) ...
的遍历顺序,部分原因是所有引擎都有自己特殊的实现,现在很难就 for-in
完整顺序规范达成一致,但规范了一些供参考的实现行为,在不同的引擎下 for in
循环出来的内容顺序是可能不一样的,现在标准化了。
可选链操作符
可选链是一个很好的语法,使用 ?.
表示,能避免一些常见类型错误。
const obj = null;
obj.a // TypeError: Cannot read properties of null (reading 'a')
obj?.a // 使用可选链之后就不会报错了,会输出 undefined
空值合并操作符
空值合并语法使用 ??
表示,和 ||
这个语法类似,不同的是 ??
有明确的规定,只有当左侧的值为 null
或 undefined
时才会返回右侧的值,例如,左侧是 0 也会认为是合法的。
const a = 0
a || 1 // 1
a ?? 1 // 0
ES2019
可选的 catch 参数
try {
throw new Error('this is not a valid')
} catch {
console.error(`error...`);
}
Symbol.prototype.description
创建 Symbol
对象时可以传入一个描述做为参数。如下所示,使用 symbol.description
可方便的获取到这个描述。
const symbol = Symbol('Hello World')
symbol.description // Hello World
函数的 toString() 方法修订
toString()
方法返回当前函数源代码的字符串,以前会省略注释和空格。
const fn = (a, b) => {
// return a + b value
const c = a + b;
return c;
}
console.log(fn.toString());
Object.fromEntries
Object.fromEntries()
方法会把键值对列表转换为对象。同 Object.entries()
相反。
const arr = [ [ 'name', 'foo' ], [ 'age', 18 ] ];
const obj = Object.fromEntries(arr);
console.log(obj); // { name: 'foo', age: 18 }
console.log(Object.entries(obj)); // [ [ 'name', 'foo' ], [ 'age', 18 ] ]
消除前后空格
ES2019 之前有一个 trim()
方法会默认消除前后空格。新增的 trimStart()
、trimEnd()
方法分别用来指定消除前面、后面空格。
' JavaScript '.trim() // 'JavaScript'
' JavaScript '.trimStart() // 'JavaScript '
' JavaScript '.trimEnd() // ' JavaScript'
数组 flat()、flatMap()
flat(depth)
可以实现数组扁平化,传入的 depth
参数表示需要扁平化的数组层级。
[['a'], ['b', 'bb'], [['c']]].flat(2) // [ 'a', 'b', 'bb', 'c' ]
flatMap()
方法是 map()
和 flat()
方法的结合,该方法只能展开一维数组。
[['a'], ['b', 'bb'], [['c']]].flatMap(x => x) // [ 'a', 'b', 'bb', [ 'c' ] ]
更友好的 JSON.stringify
对于一些超出范围的 Unicode
字符串,为其输出转义序列,使其成为有效 Unicode
。
// Before
console.log(JSON.stringify('\uD800')) // "�"
// ES2019
console.log(JSON.stringify('\uD800')) // "\ud800"
JSON 超集
之前如果 JSON 字符串中包含有行分隔符(\u2028)
和段落分隔符(\u2029)
,那么在解析过程中会报错,现在对它进行了支持。
// Before
JSON.parse('"\u2028"')
// SyntaxError
// ES2019
JSON.parse('"\u2028"')
// ''
ES2018
异步迭代器for await...of
异步迭代器(asynchronous iterators),await
可以和 for...of
循环一起使用,以串行的方式运行异步操作。
async function process(array) {
for await (let i of array) {
doSomething(i)
}
}
异步迭代在 Node.js
中用的会多些,使用 for-await-of
遍历异步数据。例如使用 MongoDB
查询数据返回值默认为一个游标对象,避免了一次性把数据读入应用内存,详情参考 github.com/qufei1993/b…
Promise.finally
Promise.finally
能保证无论执行成功或失败都一定被执行,可以用来做一些清理工作。
const connection = { open: () => Promise.resolve() }
connection
.open()
.then()
.catch()
.finally(() => {
console.log('clear connection');
})
新的正则表达式功能
- 正则命名组捕获
正则命名组捕获使用符号 ?<name>
表示,对匹配到的正则结果按名称访问。如果具名组没有匹配,那么对应的 groups
对象属性会是 undefined
。
const regexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = regexp.exec('2023-01-01');
console.log(result.groups); // { year: '2023', month: '01', day: '01' }
- 正则
Lookbehind
断言:github.com/tc39/propos…
先行断言指的是,x 只有在 y 前面才匹配,必须写成/x(?=y)/
。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/
。 先行否定断言指的是,x 只有不在 y 前面才匹配,必须写成/x(?!y)/
。比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/
。
/\d+(?=%)/.exec('100% of US presidents have been male') // ["100"]
/\d+(?!%)/.exec('that’s all 44 of them') // ["44"]
后行断言正好与先行断言相反,x 只有在 y 后面才匹配,必须写成/(?<=y)x/
。比如,只匹配美元符号之后的数字,要写成/(?<=\$)\d+/
。 后行否定断言则与先行否定断言相反,x 只有不在 y 后面才匹配,必须写成/(?<!y)x/
。比如,只匹配不在美元符号后面的数字,要写成/(?<!\$)\d+/
。
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"]
/(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"]
- 正则表达式
dotAll
模式:s 修饰符,使得.可以匹配任意单个字符。 (小数点.)默认匹配除换行符之外的任何单个字符。
例如/.n/
将会匹配 "nay, an apple is on the tree"
中的 'an'
和 'on'
,但是不会匹配 'nay'
。
如果 s ("dotAll")
标志位被设为 true
,它也会匹配换行符。
/foo.bar/.test('foo\nbar'); // → false
/foo.bar/s.test('foo\nbar'); // → true
- 正则表达式
Unicode
转义:github.com/tc39/propos…
通常使用 \d
匹配任何数字,\s
匹配任何不为空格的字符。
Unicode
属性转义,用 \p{}
匹配所有 Unicode
字符,否定为 \P{}
。
/^\p{ASCII_Hex_Digit}+$/u.test('0123456789ABCDEF') // true
/^\p{ASCII_Hex_Digit}+$/u.test('h') // false
上面代码中,ASCII_Hex_Digit
是一个布尔属性,用于检查字符串是否仅包含有效的十六进制数字。
还有许多其他布尔属性,包括 Uppercase
, Lowercase
, White_Space
, Alphabetic
, Emoji
等。
^\p{Lowercase}$/u.test('h') // true
/^\p{Uppercase}$/u.test('H') // true
/^\p{Emoji}+$/u.test('H') // false
/^\p{Emoji}+$/u.test('????????') // true
除了这些二进制属性之外,还可以检查任何 Unicode
字符属性以匹配特定值。
/^\p{Script=Greek}+$/u.test('ελληνικ?') // true
/^\p{Script=Latin}+$/u.test('hey') // true
在这个例子中,检查字符串是用希腊语还是拉丁字母写的。
Rest/Spread 属性
为对象解构提供了和数组一样的 Rest 参数和展开操作符, ES2015
中的作用对象仅限于数组;
const myObject = {
a: 1,
b: 2,
c: 3,
}
const { a, ...x } = myObject
// a = 1
// x = { b: 2, c: 3 }
function foo({ a, ...param }) {
console.log(a) // 1
console.log(param) // {b: 2, c: 3}
}
解除模版字符串限制 - Lifting template literal restriction
“Lifting template literal restriction
” 翻译过来为 “解除模版字符串限制”,这个要结合 ES6
中的 “带标签的模版字符串” 来理解。
以下代码执行时,解析器会去查找有效的转义序列,例如 Unicode
字符以 "\u"
开头,例如 \u00A9
,以下 "\unicode"
是一个非法的 Unicode
字符,在之前就会得到一个 SyntaxError: malformed Unicode character escape sequence
错误。ES2018 中解除了这个限制,当遇到不合法的字符时也会正常执行,得到的是一个 undefined
,通过 raw
属性还是可以取到原始字符串。
function tag(strs) {
console.log(strs[0]); // undefined
console.log(strs.raw[0]); // "\\unicode and \\u{55}"
}
tag`\unicode and \u{55}`
ES2017
Object.values/Object.entries
Object.values()
静态方法返回一个给定对象的自有可枚举字符串键属性值组成的数组。,同 Object.keys()
相反。
const obj = { name: 'Tom', age: 18 }
console.log(Object.values(obj)); // [ 'Tom', 18 ]
// 字符串具有索引作为可枚举的自有属性
console.log(Object.values("foo")); // ['f', 'o', 'o']
Object.entries()
静态方法返回一个数组,包含给定对象自有的可枚举字符串键属性的键值对。
const obj = { name: 'Tom', age: 18 }
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
// Output
// name Tom
// age 18
字符串补全
两个字符串补全方法 .padStart()
、.padEnd()
分别在字符串的头部、尾部进行按目标长度和指定字符进行填充。
console.log('a'.padStart(5, '1')); // 1111a
console.log('a'.padEnd(5, '2')); // a2222
async/await
异步函数 async/await
现在开发必备了,无需多讲。
-
async funciont
developer.mozilla.org/zh-CN/docs/… -
await 操作符
developer.mozilla.org/zh-CN/docs/…
async function fn() { ... }
try {
await fn();
} catch (err) {}
Object.getOwnPropertyDescriptors
Object.getOwnPropertyDescriptors()
静态方法返回给定对象的所有自有属性描述符。
const obj = {
name: 'Tom',
run: () => ``,
};
console.log(Object.getOwnPropertyDescriptors(obj));
// {
// name: {
// value: 'Tom',
// writable: true,
// enumerable: true,
// configurable: true
// },
// run: {
// value: [Function: run],
// writable: true,
// enumerable: true,
// configurable: true
// }
// }
参数列表支持尾逗号
支持在函数声明及调用时末尾增加逗号而不报 SyntaxError
错误。
function add(a, b,) {
return a + b;
}
add(1, 2,)
Shared memory and atomics
Shared memory and atomics
,“共享内存和原子” 又名 “共享数组缓冲区”,可以在主线程和多个工作线程间共享对象的字节,能更快的在多个工作线程间共享数据、除 postMessage()
多了一种数据传输方式。
多线程间的内存共享会带来一个后端常遇见的问题 “竞态条件”,提案提供了全局变量 Atomics
来解决这个问题。详情参考 2ality.com/2017/01/sha… esnext-book.lishuaishuai.com/es2017/shar…
ES2016
Array.prototype.includes
当判断一个数组中是否包含指定值时,使用 includes()
会很实用。
['a', 'b'].includes('a') // true
求幂运算符
**
是求幂运算符,左侧是基数、右侧是指数。等价于之前的 Math.pow()
函数。
2 ** 3 // 8
Math.pow(2, 3) // 8
上一篇:
小草的启示
下一篇:
春草春花日日新 (2)
上一篇: 小草的启示
下一篇: 春草春花日日新 (2)