ECMAScript 提案"通过复制更改数组": 四种新的非破坏性数组方法

1409

ECMAScript 最新提案: "通过复制更改数组",该提案为数组提供了四种新方法:

  • .toReversed()
  • .toSorted()
  • .toSpliced()
  • .with()

新提供的四种方法是非破坏性的数组方法。

破坏性数组方法

什么是破坏性的语法呐?破坏性语法是指一些数组方法会修改数组本身。

例如 sort 方法,sort 方法的返回值与调用数组指向同一对象,详情参考下面代码:

// Destructively sorting `arr`
const arr = ['c', 'a', 'b'];
const result = arr.sort();

assert.deepEqual(result, ['a', 'b', 'c']);
assert.ok(result === arr); // (A)
assert.deepEqual(arr, ['a', 'b', 'c']);

如果我们想要消除 sort 方法的破坏性,可以先复制数组,然后再更改复制后的数组。

const sorted1 = arr.slice().sort();
const sorted2 = [...arr].sort();
const sorted3 = Array.from(arr).sort();

除了 sort 方法,以下方法也具有破坏性:

  • reserve
  • splice

新的非破坏性数组方法

toReversed()

toReversed 方法是与 reverse 方法对应的非破坏性数组方法。

该方法目前为提案阶段,你可以通过 polyfill.toReversed 来使用

if (!Array.prototype.toReversed) {
  Array.prototype.toReversed = function () {
    return this.slice().reverse();
  };
}

.toSorted()

toSorted() 是与 sort() 对应的非破坏性数组方法。

该方法目前为提案阶段,你可以通过 polyfill.toSorted 来使用

if (!Array.prototype.toSorted) {
  Array.prototype.toSorted = function (compareFn) {
    return this.slice().sort(compareFn);
  };
}

toSpliced(start, deleteCount, ...items)

splice 方法的破坏性非常复杂,它的具体机制是这样的:

  • 从索引 start 开始,删除 deleteCount 数量的元素
  • 可以在索引 start 位置插入元素
  • 返回被删除的元素

toSpliced() 是与 splice() 对应的非破坏性数组方法。由于它需要返回调用数组的更改版本,因此不允许访问已删除元素。

该方法目前为提案阶段,你可以通过 polyfill.toSpliced 来使用

if (!Array.prototype.toSpliced) {
  Array.prototype.toSpliced = function (start, deleteCount, ...items) {
    const copy = this.slice();
    copy.splice(start, deleteCount, ...items);
    return copy;
  };
}

with

with 方法没有对应的破坏性方法,它的功能是非破坏性的修改索引 index 对应的元素值(即非破坏的 arr[index]=value)

该方法目前为提案阶段,你可以通过 polyfill.with 来使用

if (!Array.prototype.with) {
  Array.prototype.with = function (index, value) {
    const copy = this.slice();
    copy[index] = value;
    return copy;
  };
}

新方法适用于元组

新提议的 Tuple 特性本质上是一个不可变的数组,因此元组具有数组的所有方法(破坏性方法除外),因此后续添加的非破坏性方法元组也是可以使用的。

如果你想了解当前提案的更多讯息,参考 2ality.com/2022/04/cha…