ES6 是 2015 年提出的,按照这个逻辑 ES2023 应该叫做 ES14,为了避免混淆,我们就用年份来命名。为了赶上 ES 标准迭代的步伐,我们一起来看看 2023 年又加入了哪些新特性。
一、从尾部查找
涉及到两个函数
findLast / findLastIndex
findLast / findLastIndex 基本用法
const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
// findLast
array.findLast((n) => n.value % 2 === 1) // { value: 3 }
// findLastIndex
array.findLastIndex((n) => n.value % 2 === 1) // 2
array.findLastIndex((n) => n.value === 42) // -1
find 和 findIndex 的基本用法
const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
//find和findIndex的基本用法
array.find((n) => n.value % 2 === 1) // { value: 1 }
array.findIndex((n) => n.value % 2 === 1) // 0
以前的想要从后往前查的方案和痛点
const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
// find
;[...array].reverse().find((n) => n.value % 2 === 1) // { value: 3 }
// findIndex
array.length - 1 - [...array].reverse().findIndex((n) => n.value % 2 === 1) // 2
array.length - 1 - [...array].reverse().findIndex((n) => n.value === 42) // should be -1, but 4
二、Hashbang 语法
Hashbang 也叫 Shebang,是一个由井号和叹号构成的字符序列 #!,用来指定使用哪种解释器执行此文件:
#!/usr/bin/env node
"use strict"
console.log(1)
在终端执行,没有 Hashbang 时,需要使用 node 指令才能执行node xxx
有 Hashbang 时,可以直接./xxxxx
执行
三、WeakMap 支持 Symbol 作为 key
const weak = new WeakMap()
// Pun not intended: being a symbol makes it become a more symbolic key
const key = Symbol("my ref")
const someObject = {
/* data data data */
}
weak.set(key, someObject)
四、通过复制更改 Array
Array.prototype.toReversed() -> Array
Array.prototype.toSorted(compareFn) -> Array
Array.prototype.toSpliced(start, deleteCount, ...items) -> Array
Array.prototype.with(index, value) -> Array
toSorted
Array
实例的 toSorted()
方法是 sort()
方法的复制方法版本。它返回一个新数组,其元素按升序排列。
const months = ["Mar", "Jan", "Feb", "Dec"];
const sortedMonths = months.toSorted();
console.log(sortedMonths); // ['Dec', 'Feb', 'Jan', 'Mar']
console.log(months); // ['Mar', 'Jan', 'Feb', 'Dec']
const values = [1, 10, 21, 2];
const sortedValues = values.toSorted((a, b) => a - b));
console.log(sortedValues); // [1, 2, 10, 21]
console.log(values); // [1, 10, 21, 2]
console.log(["a", "c", , "b"].toSorted()) // ['a', 'b', 'c', undefined]
console.log([, undefined, "a", "b"].toSorted()) // ["a", "b", undefined, undefined]
const arrayLike = {
length: 3,
unrelated: "foo",
0: 5,
2: 4,
}
console.log(Array.prototype.toSorted.call(arrayLike))
// [4, 5, undefined]
toSpliced()
Array
实例的 toSpliced()
方法是 splice()
方法的复制版本。它返回一个新数组,并在给定的索引处删除和/或替换了一些元素。
toSpliced(start)
toSpliced(start, deleteCount)
toSpliced(start, deleteCount, item1)
toSpliced(start, deleteCount, item1, item2, itemN)
const months = ["Jan", "Mar", "Apr", "May"]
// 在索引 1 处添加一个元素
const months2 = months.toSpliced(1, 0, "Feb")
console.log(months2) // ["Jan", "Feb", "Mar", "Apr", "May"]
// 从第 2 个索引开始删除两个元素
const months3 = months2.toSpliced(2, 2)
console.log(months3) // ["Jan", "Feb", "May"]
// 在索引 1 处用两个新元素替换一个元素
const months4 = months3.toSpliced(1, 1, "Feb", "Mar")
console.log(months4) // ["Jan", "Feb", "Mar", "May"]
// 原数组不会被修改
console.log(months) // ["Jan", "Mar", "Apr", "May"]
const arr = [1, , 3, 4, , 6]
console.log(arr.toSpliced(1, 2)) // [1, 4, undefined, 6]
const arrayLike = {
length: 3,
unrelated: "foo",
0: 5,
2: 4,
}
console.log(Array.prototype.toSpliced.call(arrayLike, 0, 1, 2, 3))
// [2, 3, undefined, 4]
toReversed
Array
实例的 toReversed()
方法是 reverse()
方法对应的复制版本。它返回一个元素顺序相反的新数组。
const items = [1, 2, 3]
console.log(items) // [1, 2, 3]
const reversedItems = items.toReversed()
console.log(reversedItems) // [3, 2, 1]
console.log(items) // [1, 2, 3]
console.log([1, , 3].toReversed()) // [3, undefined, 1]
console.log([1, , 3, 4].toReversed()) // [4, 3, undefined, 1]
const arrayLike = {
length: 3,
unrelated: "foo",
2: 4,
}
console.log(Array.prototype.toReversed.call(arrayLike))
// [4, undefined, undefined]
// '0' 和 '1' 两个索引不存在,所以它们会变成 undefined
with()
Array
实例的 with()
方法是使用方括号表示法修改指定索引值的复制方法版本。它会返回一个新数组,其指定索引处的值会被新值替换。
const arr = [1, 2, 3, 4, 5]
console.log(arr.with(2, 6)) // [1, 2, 6, 4, 5]
console.log(arr) // [1, 2, 3, 4, 5]
const arr = [1, 2, 3, 4, 5]
console.log(arr.with(2, 6).map((x) => x ** 2)) // [1, 4, 36, 16, 25]
const arr = [1, , 3, 4, , 6]
console.log(arr.with(0, 2)) // [2, undefined, 3, 4, undefined, 6]
const arrayLike = {
length: 3,
unrelated: "foo",
0: 5,
2: 4,
}
console.log(Array.prototype.with.call(arrayLike, 0, 1))
// [ 1, undefined, 4 ]
注意:
此次发布的新方法不仅适用于常规的数组对象。可以在任意 TypedArray 上使用 toSorted、toReversed 和 with 方法,包括 Int8Array 到 BigUint64Array 等各种类型。但因为 TypedArrays 没有 splice 方法,因此无法使用 toSpliced 方法。
Array 的 map、filter 和 concat 等方法也都采取先复制再更改的思路,但这些方法与新的复制方法间仍有不同。如果对内置的 Array 对象进行扩展,并在实例上使用 map、flatMap、filter 或 concat,则会返回相同类型的新实例。但如果您扩展一个 Array 并使用 toSorted、toReversed、toSpliced 或者 with,则返回的仍是普通 Array。
class MyArray extends Array {}
const languages = new MyArray("JavaScript", "TypeScript", "CoffeeScript")
const upcase = languages.map((language) => language.toUpperCase())
console.log(upcase instanceof MyArray)
// => true
const reversed = languages.toReversed()
console.log(reversed instanceof MyArray)
// => false
可以使用 MyArray.from 将其转回您的自定义 Array:
class MyArray extends Array {}
const languages = new MyArray("JavaScript", "TypeScript", "CoffeeScript");
const reversed = MyArray.from(languages.toReversed());
console.log(reversed instance of MyArray);
// => true
参考
https://github.com/tc39/proposals/blob/HEAD/finished-proposals.md