ES2016 - ES2024 新特性速览
JavaScript 由 Brendan Eich 于 1995 年发明,并于1997年成为 ECMA 标准。
ECMAScript 的版本缩写为 ES1、ES2、ES3、ES5 和 ES6,但自 2016 年起,版本按年份命名(ECMAScript 2016、2017、...、2023,简称为 ES2016、ES2017、...、ES2023)。
本文是对 ECMAScript 不同版本引入的新特性和语言增强功能的一次整理和备忘,按倒序阐述,主要内容如下:
ECMAScript 2023 / ES2023 ECMAScript 2022 / ES2022 ... ECMAScript 2017 / ES2017 ECMAScript 2016 / ES2016 ECMAScript 2024 前瞻
1.ECMAScript 2023 / ES2023
1.1.Array find from last
let nums = [5,4,3,2,1];
let lastEven = nums.findLast((num) => num % 2 === 0); // 2
let lastEvenIndex = nums.findLastIndex((num) => num % 2 === 0); // 3
1.2.Hashbang Grammer
该功能将使我们能够在某些 CLI 中使用 Hashbang / Shebang。Shebang 用 #! 表示,是脚本开头的一行特殊行,用于告诉操作系统在执行脚本时使用哪个解释器。
#!/usr/bin/env node
// in the Script Goal
'use strict';
console.log(2*3);
#!/usr/bin/env node
// in the Module Goal
export {};
console.log(2*2);
1.3.Symbols as WeakMap keys
它允许使用唯一的符号作为键。目前,WeakMaps 只允许将对象作为键。对象之所以被用作弱映射的键,是因为它们具有相同的身份特征。Symbol 是 ECMAScript 中唯一允许唯一值的原始类型,因此可以使用 Symbol 作为键,而不是使用 WeakMap 创建一个新对象。
const weak = new WeakMap();
const key = Symbol('my ref');
const someObject = { a:1 };
weak.set(key, someObject);
// Output: {a: 1}
console.log(weak.get(key));
1.4.Change Array by Copy
为 Array.prototype 提供了额外的方法,通过返回包含更改的新副本来更改数组,而不是更新原始数组。
新引入的 Array.prototype 函数包括:
Array.prototype.toReversed()
Array.prototype.toSorted(compareFn)
Array.prototype.toSpliced(start, deleteCount, ...items)
Array.prototype.with(index, value)
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
/* toReversed */
const reversed = numbers.toReversed();
console.log("reversed", reversed); // "reversed", [9, 8, 7, 6, 5, 4, 3, 2, 1]
console.log("original", numbers); // "original", [1, 2, 3, 4, 5, 6, 7, 8, 9]
/* toSorted */
const sortedArr = numbers.toSorted();
console.log("sorted", sortedArr); // "sorted", [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log("original", numbers); // "original", [1, 2, 3, 4, 5, 6, 7, 8, 9]
/* with */
const replaceWith = numbers.with(1, 100);
console.log("with", replaceWith); // "with", [1, 100, 3, 4, 5, 6, 7, 8, 9]
console.log("original", numbers); // "original", [1, 2, 3, 4, 5, 6, 7, 8, 9]
/* toSpliced */
const splicedArr = numbers.toSpliced(0, 4);
console.log("toSpliced", splicedArr); // "toSpliced", [5, 6, 7, 8, 9]
console.log("original", numbers); // "original", [1, 2, 3, 4, 5, 6, 7, 8, 9]
2.ECMAScript 2022 / ES2022
ES2022 是 JavaScript 的第 13 版,于 2022 年 6 月发布,让我们来看看该版本新增的特性及功能。
2.1.Top-level await
在此之前,我们只能在 async function
的作用域中使用 await
。这种情况一直很好,直到出现问题,比如当我们进入模块的顶层时,就无法使用 await
关键字了。现在,await
可以在模块的顶层使用,在初始化导入和创建回退时非常方便。
//The old behavior
await Promise.resolve(console.log('Hello World'));
// Output: SyntaxError: await is only valid in async function
// Alternative to fix the problem
(async function() {
await Promise.resolve(console.log('Hello World'));
// Output: Hello World
}());
await Promise.resolve(console.log('Hello World'));
// → Hello World
//Dynamic dependency pathing
const strings = await import(`/i18n/${navigator.language}`);
//Resource initialization
const connection = await dbConnector();
// Dependency fallbacks
let jQuery;
try {
jQuery = await import('https://cdn-a.com/jQuery');
} catch {
jQuery = await import('https://cdn-b.com/jQuery');
}
2.2.Private instance fields, methods, and accessors
以前,如果需要声明私有方法或字段,需要在方法名称开头添加下划线(基于惯例),但这并不能保证该方法是私有的。ES2022 增加了私有实例字段、方法和访问器等新功能。我们只需在方法名开头添加 **#**,这样就能将方法声明为私有方法。
// 1) Private class fields
class Test {
#firstName = 'test-name';
}
const test = new Test();
// Output: undefined
console.log(test.firstName);
// 2) Private class methods
class Test {
#addTestRunner(testRunner){
this.testRunner = testRunner
}
}
const test = new Test();
// Output: TypeError: test.addTestRunner is not a function
test.addTestRunner({name: 'test'});
// 3) Private accessors (getters and setters)
// 以前需要声明 getter 或 setter 时,可以通过创建的实例进行访问,ES2022 增加了私有访问器这一新功能。
class Test {
get #name(){
return 'test-name';
}
}
const test = new Test();
// Output: undefined
console.log(test.name);
2.3.Static class fields and methods
静态类字段和方法不用于类的实例。相反,它们可以在类本身上调用,并使用 static
关键字声明。静态方法通常是实用函数和辅助工具,而静态属性则适用于缓存、固定配置或其他不需要在实例间复制的数据。
// 1) Static class fields
class Test {
static firstName = 'test-static-name';
}
// Output: test-static-name
console.log(Test.firstName)
// 2) Static class methods
class Test {
static greeting(){
console.log('Hello this is a greeting from a static method');
}
}
// Output: Hello this is a greeting from a static method
Test.greeting();
注意:我们在这些示例中使用的是静态公共字段和方法,但我们也可以创建静态私有字段和方法。
2.4.Static class initialization blocks
这项新功能为类定义评估期间的额外静态初始化提供了一种机制。
class Test {
static numbers = [1,2,3,4,5,6];
static evenNumbers = [];
static oddNumbers = [];
// static class initialization block
static {
this.numbers.forEach((number) => {
if(!(number % 2) ) {
this.evenNumbers.push(number);
} else {
this.oddNumbers.push(number);
}
});
}
}
Test.evenNumbers;
// Output: [2, 4, 6]
Test.oddNumbers;
// Output: [1, 3, 5]
2.5.Error: .cause
Error
及其子类现在可以让我们指定错误背后的原因。有时,我们会捕捉到在更深的嵌套函数调用过程中抛出的错误,并希望为它们附加更多信息。有了错误原因,我们就可以为错误添加更多内在信息。要使用这一新功能,我们应将错误选项指定为第二个参数,并通过原因键传递我们希望链式处理的错误。
const getUsers = async(array)=> {
try {
const users = await fetch('https://myapi/myusersfake');
return users;
} catch (error) {
console.log('enter')
throw new Error('Something when wrong, please try again later', { cause: error })
}
}
try{
const users = await getUsers();
} catch(error) {
console.log(error); // Error: The array need a minimum of two elements
console.log(error.cause); // TypeError: Failed to fetch
}
2.6.Array, String, and TypedArray: .at() Method
在此之前,程序员一直要求能像其他编程语言一样,对 JS 数组进行负索引。也就是说,要求能写 arr[-1]
而不是 arr[arr.length-1]
,负数从最后一个元素开始向后计数。
在 ECMAScript 2022 中,有了一个很大的变化,那就是有了一个新方法来帮助程序员实现负数索引,即 Array
、String
或 TypedArray
所支持的 .at()
方法。
// 1) old
const fruits = ['banana', 'apple', 'orange', 'kiwi'];
// Output: kiwi
console.log(fruits[fruits.length -1])
const fruit = 'kiwi';
// Output: i
console.log(fruit[fruit.length -1])
// 2) new
const fruits = ['banana', 'apple', 'orange', 'kiwi'];
// Output: kiwi
console.log(fruits.at(-1))
const fruit = 'kiwi';
// Output: i
console.log(fruit.at(-1))
注意:.at()
也接受正数,因此在需要索引时,它可以作为另一种方法使用。
2.7.Object: .hasOwn()
// old behavior
let hasOwnProperty = Object.prototype.hasOwnProperty
if (hasOwnProperty.call(object, "foo")) {
console.log("has property foo")
}
// new behavior
if (Object.hasOwn(object, "foo")) {
console.log("has property foo")
}
2.8.RegExp: match .indices ('d' flag)
新的 /d flag 功能提供了输入字符串中每个匹配的起始和索引位置结束的一些附加信息。
// old behavior
const regexExample = /greeting(\d)/g;
const exampleString = 'greeting1greeting2';
// Output:
// ['greeting1', '1', index: 0, input: 'greeting1greeting2', groups: undefined]
// ['greeting2', '2', index: 9, input: 'greeting1greeting2', groups: undefined]
console.log(...exampleString.matchAll(regexExample));
// new behavior
const regexExample2022 = /greeting(\d)/dg;
const exampleString = 'greeting1greeting2';
// Output:
// ['greeting1', '1', index: 0, input: 'greeting1greeting2', groups: undefined, indices: Array(2)]
// ['greeting2', '2', index: 9, input: 'greeting1greeting2', groups: undefined, indices: Array(2)]
console.log(...exampleString.matchAll(regexExample2022));
3.ECMAScript 2021 / ES2021
ES2021 是 TC39 委员会批准的第 12 个 ECMAScript 版本。它包含了每个 JavaScript 开发人员都应该了解的一些令人兴奋的功能。
3.1.Promise.any method
ES2020 引入了 promise.all()
,用于并发运行多个 promise,并在所有 promise 处理完毕(履行或拒绝)后采取行动。ES2021 引入了 Promise.any(),它可以处理承诺数组。
ES2021 引入了 Promise.any()
,它可以同时运行多个 promise ,并在它们全部被解决(满足或拒绝)时执行操作。Promise.any()
方法接受一个 promise 列表,并返回第一个被解决的 promise 的值。在下面的示例中,我们将两个 promise 传递给 Promise.any()
方法,它将在第一个promise被解决时立即给出输出结果。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "1 second");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, "2 second");
});
const promises = [promise1, promise2];
Promise.any(promises).then((value) => {
// outputs “1 second”
console.log(value);
});
3.2.Numberic separators
这个特性允许数字字面量使用下划线作为分隔符,通过在数字组之间进行视觉分隔来提高可读性。
// A billion
const amount = 1_000_000_000;
// Hundreds of millions
const amount = 1_475_938.38;
// 6234500 cents (62345 dollars)
const amount = 62345_00;
// 1,734,500
const amount = 1_734_500;
// 20^30000
const amount = 2e30_000;
// Also can be used for Binary, Hex, Octal bases
3.3.String.protype.replaceAll
日常开发中,如果我们不使用 regexp 的全局 flag (/regex/g),就无法替换子串的所有实例。有了这个新方法 replaceAll,会方便很多。
/* before */
const message = 'hello+this+is+a+message';
const messageWithSpace = message.replace(/\+/g, ' ');
// Output: hello this is a message
console.log(messageWithSpace);
/* after */
const message = 'hello+this+is+a+message';
const messageWithSpace = message.replaceAll('+', ' ')
// Output: hello this is a message
console.log(messageWithSpace);
3.4.Logical assignment operator
逻辑赋值运算符结合了逻辑运算符和赋值表达式。
以下是一些新的运算符:
And & Equals (&&=) OR & Equals (||=) Nullish Coalescing & Equals (??=)
And & Equals (&&=)
当值为真时进行赋值,具体如下表:
x | y | x And & Equals y | x after assign |
---|---|---|---|
true | true | true | true |
true | false | false | false |
false | true | false | false |
false | false | false | false |
/* before */
let a = 1;
if(a){
a = 8;
}
// Output: a = 8
/* after */
let a = 1;
a &&= 3
// Output: a = 3
OR & Equals (||=)
当值为假时进行赋值,具体如下表:
x | y | x OR & Equals y | x after assign |
---|---|---|---|
true | true | true | true |
true | false | true | true |
false | true | true | true |
false | false | false | false |
/* before */
// If conditional
let a = undefined;
if(!a){
a = 5;
}
// OR
a = a || 5;
// Output: a = 5
/* after */
let a = undefined;
a ||= 5
// Output: a = 5
Nullish Coalescing & Equals (??=)
当值为 null
或 undefined
时进行赋值。
let a = undefined;
a ??= 5
// Output: a = 5
3.5.WeakRef
WeakRef(弱引用)允许您创建一个对对象的弱引用。对对象的弱引用是在垃圾收集器回收对象时不会阻止其回收的引用。弱引用的主要用途是实现大对象的缓存或映射。在这种情况下,期望大对象不仅仅因为出现在缓存或映射中而被保持活动。
const objectExample = {name: "Juanito", lastname: "Jordan"};
const refObj = new WeakRef(objectExample);
当需要读取 WeakRefs 的值时,需要使用 deref() 方法返回实例。
const obj = refObj.deref();
// Output: 'Juanito'
console.log(obj.name);
4.ECMAScript 2020 / ES2020
ES2020 是 TC39 委员会批准的第 11 个 ECMAScript 版本。
4.1.Bigint
BigInt
是 JavaScript 中新的第 7 种基本数据类型,可以说是 ES2020 中最大的新成员。它允许开发人员处理一些非常大的整数。
“通常”数字类型可以处理的最大整数等于 2^53 - 1 或 9007199254740991。您可以通过 MAX_SAFE_INTEGER 常量访问该值。
Number.MAX_SAFE_INTEGER; // 9007199254740991
顾名思义,操作超过此值的数字可能有一些问题。对于BigInt,除了设备的内存外,没有任何限制。要定义一个BigInt,您可以使用BigInt()函数并提供一个表示大值的字符串,或者使用类似于普通数字的语法,但以n结尾。
const myBigInt = BigInt("999999999999999999999999999999");
const mySecondBigInt = 999999999999999999999999999999n;
typeof myBigInt; // "bigint"
重要的是要知道BigInt与“通常”数字不完全兼容。这意味着当您确定将处理真正大的数字时,您很可能只想使用BigInt。
const bigInt = 1n; // 小数字,但仍属于BigInt类型
const num = 1;
num === bigInt; // false -> 它们不是严格相等的
num == bigInt; // true
num >= bigInt; // true -> 它们可以比较
num + bigInt; // error -> 它们不能相加
总的来说,对于那些在JS中进行一些复杂的数学计算的人来说,BigInt
非常有用。它们很好地取代了那些仅用于处理大数的奇怪和速度差的库。或者至少是整数,因为我们仍然没有听说过 BigDecimal
提案的太多内容。
4.2.Dynamic imports
对应开发者来说,对 Dynamic imports
功能并不陌生。因为早在 2017 年底,V8 就引入了这一功能!
import("module.js").then((module) => {
// ...
});
// or
async () => {
const module = await import("module.js");
};
4.3.Nullish coalescing operator
Nullish coalescing 运算符 (??
) 是一种新的 JS 运算符,当访问的值为 null
或 undefined
时,它可以提供一个 "默认值"。
const basicValue = "test";
const nullishValue = null;
const firstExample = basicValue ?? "example"; // "test"
const secondExample = nullishValue ?? "example"; // "example"
4.4.Optional chaining operator
与 ??
操作符类似,可选链式操作符也处理 null
和 undefined
值,但这次是在对象中。以前尝试访问空值上的属性会导致错误,而现在可选链式操作符 (?.) 将继续 "返回 "空值。
const obj = {
prop: {
subProp: {
value: 1,
},
},
};
/* before */
obj.prop.subProp.value; // 1
obj.prop.secondSubProp.value; // error
/* after */
obj?.prop?.subProp?.value; // 1
obj?.prop?.secondSubProp?.value; // undefined
4.5.Exporting modules
添加了一个新语法,和导入模块模块,允许导出模块,请参见下面的示例:
// Existing in JS
import * as MyComponent from './Component.js'
// Added in ES11
export * as MyComponent from './Component.js'
4.6.Promise.AllSettled
ES2020 新增了 Promise.allSettled()
方法。它与已有的 Promise.all()
方法类似,主要区别是 Promise.all()
会在所有 promise 都成功时成功,有一个失败时即失败。而 Promise.allSettled()
无论 promise 成功或者失败都会返回。
const promises = [
new Promise((resolve, reject) => {
reject('failed')
}),
new Promise((resolve, reject) => {
resolve('success')
}),
];
Promise.allSettled(promises).then((data) => {
// Output: [{"status":"rejected","reason":"failed"},{"status":"fulfilled","value":"success"}]
console.log(JSON.stringify(data));
});
4.7.String.matchAll()
String.matchAll() 在设置 g
flag 时,可以替换循环中 RegExp.exec()
的功能。
const year = new Date().getFullYear().toString();
const regexp = /\d/g;
const matchedArr = year.matchAll(regexp);
// Output:
// ['2', index: 0, input: '2023', groups: undefined]
// ['0', index: 1, input: '2023', groups: undefined]
// ['2', index: 2, input: '2023', groups: undefined]
// ['3', index: 3, input: '2023', groups: undefined]
console.log(...matchedArr);
4.8.For-in order
ES2020 规范中严格定义了 for...in
循环的迭代顺序。
5.ECMAScript 2019 / ES2019
5.1.Array.prototype.{flat,flatMap}
使用 flat()
方法可以轻松连接数组的所有子数组元素。
const arr = [10, [20, [30]]];
console.log(arr.flat()); // => [10, 20, [30]]
console.log(arr.flat(1)); // => [10, 20, [30]]
console.log(arr.flat(2)); // => [10, 20, 30]
flatMap()
方法将 map()
和 flat()
方法合二为一。它首先用所提供函数的返回值创建一个新数组,然后将数组的所有子数组元素连接起来。
console.log(arr.map(value => [Math.round(value)]));
// => [[4], [20], [26]]
console.log(arr.flatMap(value => [Math.round(value)]));
// => [4, 20, 26]
5.2.String.prototype.{trimStart,trimEnd, matchAll*}
const data = " Hacker Rank ";
// Output: "Hacker Rank "
console.log(data.trimStart());
// Output: " Hacker Rank"
console.log(data.trimEnd());
// Output: ["a", index: 2, input: " Hacker Rank ", groups: undefined]
console.log(data.match("a"));
const matchedArr = data.matchAll("a");
// Output:
// ["a", index: 2, input: " Hacker Rank ", groups: undefined]
// ["a", index: 9, input: " Hacker Rank ", groups: undefined]
console.log(...matchedArr);
5.3.Function.prototype.toString
如果函数编写的是 ECMAScript 代码,则 toString 应返回源代码。对于内置函数和绑定函数,它返回 NativeFunction 字符串。
function multiply(a, b) {
return a * b;
}
// Output:
// function multiply(a, b) {
// return a * b;
// }
console.log(multiply.toString());
const add = new Function('a', 'b', 'return a+b');
// Output:
// function anonymous(a,b) {
// return a+b
// }
console.log(add.toString());
// Output: function stringify() { [native code] }
console.log(JSON.stringify.toString());
5.4.Object.fromEntries
const versions = [
['one', 'alpha'],
['two', 'beta'],
['three', 'gamma']
];
// Output: {one: 'alpha', two: 'beta', three: 'gamma'}
console.log(Object.fromEntries(versions));
5.5.Symbol.prototype.description
创建 Symbol
时,可以为其添加描述以进行调试。有时,在代码中直接访问描述非常有用。
这个 ES2019 提案在 Symbol 对象中添加了一个只读的 description 属性,该属性返回一个字符串,其中包含Symbol的描述信息。
const sym = Symbol('foo');
// Output: foo
console.log(sym.description);
const sym = Symbol();
// Output: undefined
console.log(sym.description);
// create a global symbol
const sym = Symbol.for('bar');
// Output: bar
console.log(sym.description);
5.6.Optional catch binding
这是对 ECMAScript 规范的一个小改动,可以省略 catch 绑定及其周围的括号.
try {
// use a feature that the browser might not have implemented
} catch {
// do something that doesn’t care about the value thrown
}
6.ECMAScript 2018 / ES2018
6.1.Async iterators
异步迭代器与迭代器类似,但这一次,next() 返回一个 promise。该 promise 的解析元组为 { value, done }。之所以需要返回一个 promise,是因为在迭代器返回时,value 和 done 的值是未知的。
function asyncIterator() {
const array = [1, 2];
return {
next: function() {
if (array.length) {
return Promise.resolve({
value: array.shift(),
done: false
});
} else {
return Promise.resolve({
done: true
});
}
}
};
}
var iterator = asyncIterator();
(async function() {
await iterator.next().then(console.log); // { value: 1, done: false }
await iterator.next().then(console.log); // { value: 2, done: false }
await iterator.next().then(console.log); // { done: true }
})();
6.2.Object rest properties
const { fname, lname, ...rest } = { fname: "Hemanth", lname: "HM", location: "Earth", type: "Human" };
// Output: Hemanth
console.log(fname);
// Output: {location: "Earth", type: "Human"}
console.log(rest);
6.3.Object spread properties
const info = {fname, lname, ...rest};
// Output: { fname: "Hemanth", lname: "HM", location: "Earth", type: "Human" }
console.log(info);
6.4.Promise prototype finally
Promise API 通过一个可选的 finally 块进行了扩展,该块在任何情况下(在 Promise 被解决或拒绝后)都会被调用。
function testFinally() {
return new Promise((resolve,reject) => resolve())
}
// Output:
// resolved
// finally
testFinally().then(() => console.debug("resolved")).finally(() => console.debug("finally"))
7.ECMAScript 2017 / ES2017
7.1.async function
async
和 await
使 Promise
更容易编写,async
函数返回 Promise,await
使函数等待 Promise
。await
关键字只在常规 JavaScript 代码中的 async
函数内有效。如果在 async
函数的主体之外使用该关键字,则会出现语法错误(SyntaxError)。
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
// expected output: "resolved"
}
asyncCall();
7.2.Object.entries()
JavaScript 的 Object.entries()
方法用于返回给定对象自身可枚举属性 [key, value]
对的数组。
const fruits = {
apple: 10,
orange: 20,
grapes: 30,
pineapple: 40
};
// Output: ['apple_10', 'orange_20', 'grapes_30', 'pineapple_40']
console.log(Object.entries(fruits).map((([key, value]) => `${key}_${value}`)));
7.3.Object.values()
Object.values
可以让我们返回一个数组,其中包含给定对象自身的可枚举属性值。顺序与 for...in
循环提供的顺序相同。
const fruits = {
apple: 10,
orange: 20,
grapes: 30,
pineapple: 40
};
// Output: 100
console.log(Object.values(fruits).reduce((a, b) => a + b))
7.4.Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 返回给定对象的所有自有的 value
, writable
, get
, set
, configurable
, enumerable
等属性描述符。
let myObj = {
property1: 'foo',
property2: 'bar',
property3: 42,
property4: () => console.log('prop4')
}
Object.getOwnPropertyDescriptors(myObj)
/*
{ property1: {…}, property2: {…}, property3: {…}, property4: {…} }
property1: {value: "foo", writable: true, enumerable: true, configurable: true}
property2: {value: "bar", writable: true, enumerable: true, configurable: true}
property3: {value: 42, writable: true, enumerable: true, configurable: true}
property4: {value: ƒ, writable: true, enumerable: true, configurable: true}
__proto__: Object
*/
7.5.Trailing Commas
这种代码风格对 Code Review 是有利的,会明显减少代码行数的变更。
var list = [
"one",
"two",
"three", // It is valid
]
const func = (a,b,c,) => {
// no error occurs
};
7.6.string.padEnd() and string.padStart()
在 JavaScript 中,字符串填充一直备受争议。流行的 left-pad 库引起了一家同名即时通讯应用的代理律师的注意,之后该库被从 npm 中删除。不幸的是,数以千计的项目都将其作为依赖库使用,因此引发了互联网上的轩然大波。随后,npm 更改了操作流程,left-pad 也就不再发布了。
ES2017 新增了本地字符串填充功能,因此无需使用第三方模块。``.padStart()和
.padEnd()` 可分别在字符串的开头或结尾添加字符,直至达到所需的长度。两者都接受最小长度和可选的 "填充 "字符串(默认为空格)作为参数。示例
'abc'.padStart(5); // ' abc'
'abc'.padStart(5, '-'); // '--abc'
'abc'.padStart(10, '123'); // '1231231abc'
'abc'.padStart(1); // 'abc'
'abc'.padEnd(5); // 'abc '
'abc'.padEnd(5, '-'); // 'abc--'
'abc'.padEnd(10, '123'); // 'abc1231231'
'abc'.padEnd(1); // 'abc'
8.ECMAScript 2016 / ES2016
8.1.Array.prototype.includes
arr.includes(searchEl[, fromIndex])
,这个方法有点像 indexOf()
,对语言非常有用,它返回 true 或 false,而不是索引。
[1, 2, 3].includes(-1) // false
[1, 2, 3].includes(1) // true
[1, 2, 3].includes(3, 4) // false
[1, 2, 3].includes(3, 3) // false
[1, 2, NaN].includes(NaN) // true
['foo', 'bar', 'quux'].includes('foo') // true
['foo', 'bar', 'quux'].includes('norf') // false
let arr = ['x', 'y', 'z'];
arr.includes('x', 3) // false
arr.includes('z', 100) // false
8.2.Exponential Operator
// Output: 8
Math.pow(2, 3);
let cubed = x => x ** 3;
// Output: 8
console.log(cubed(2))
9.ECMAScript 2024 前瞻
到目前为止,有三个处于完成状态(第4阶段)的提案,并计划在 ECMAScript 2024 快照中纳入。
9.1.Well-Formed Unicode Strings
独立代理字符串是指包含 0xD800-0xDBFF 至 0xDC00-0xDFFF 范围内的 Unicode 字符的字符串。如果一个字符串包含一个独立的代理字符,那么这个字符串就不是格式正确的字符串。本建议引入了两种新方法,有助于处理非良好格式字符串
String.prototype.isWellFormed
如果字符串不包含单独的代理,则返回 true。这对于 JavaScript/web APIS 之间的接口尤其有用。
const str1 = "ab\uD800";
const str2 = "abc";
console.log(str1.isWellFormed()); //false
console.log(str2.isWellFormed()); //true
String.prototype.toWellFormed
将字符串中的所有单个代理项替换为 Unicode 替代字符U+FFFD并返回字符串。这模拟了非ECMAScript API中已经执行的操作。
const str1 = "ab\uD800";
const str2 = "abc";
console.log(str1.toWellFormed()); //ab�
console.log(str2.toWellFormed()); // abc
9.2.Regular Expression v flag with set notation and properties of strings
正则表达式是 JavaScript 中最有益的工具之一,自1999年以来一直得到支持。多年来,它们不断得到改进,并且看起来ES2024将会获得更多增强。它将引入通过 v
标志启用的 unicodeSets 模式。该标志的显着特点包括字符串的 Unicode 属性、集合表示和改进的反向字符类的不区分大小写匹配。
9.3.Atomics.waitAsync
这个方法已经在流程中有一段时间了,但在 2023年5月的 TC39 会议上达到了第4阶段的状态。它是一个静态方法,可异步等待共享内存位置,并返回一个Promise。与 Atomics.wait()
不同,它是非阻塞的,可以在主线程上使用。
const arrayBuffer = new SharedArrayBuffer(1024);
const arr = new Int32Array(arrayBuffer);
//This will wait for position 0 on the int32 array and expect a result of 0,
//waiting for 500 ms
Atomics.waitAsync(arr, 0 , 0 , 500);
// { async: true, value: Promise {<pending>}}
//the notify method awakes the array and the promise is fulfilled
Atomics.notify(arr, 0);
// { async: true, value: Promise {<fulfilled>: 'ok'} }
大家都在看