一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情
该提案地址为“Change Array by copy”,由Robin Ricard 和 Ashley Claymore提出,目前以进入state3阶段。
TC39规范
首先让我们来了解一下,对于一个提案从提出到最后被纳入ES新特性,在TC39规范中需要分那几步来走呢:
- stage0(strawman),任何TC39的成员都可以提交。
- stage1(proposal),进入此阶段就意味着这一提案被认为是正式的了,需要对此提案的场景与API进行详尽的描述。
- stage2(draft),演进到这一阶段的提案如果能最终进入到标准,那么在之后的阶段都不会有太大的变化,因为理论上只接受增量修改。
- state3(candidate),这一阶段的提案只有在遇到了重大问题才会修改,规范文档需要被全面的完成。
- state4(finished),这一阶段的提案将会被纳入到ES每年发布的规范之中。 这意味着该提案在不远的将来即将被浏览器实现支持。
破坏性与非破坏性数组方法
大部分数组方法都是非破坏性的-它们不会改变原数组,如filter方法:
const arr = ['a', 'b', 'b', 'a'];
const result = arr.filter(x => x !== 'b');
console.log(arr)//['a', 'b', 'b', 'a'];
console.log(result)//['a', 'a']
但是也有一下数组方法是破环性,他们改变原数组,如 .sort():
const arr = ['c', 'a', 'b'];
const result = arr.sort();
console.log(arr)//['a', 'b', 'c']
console.log(result)//['a', 'b', 'c']
除.sort()方法外,以下两个个方法也具有破环性:
.reverse().splice()如果我们在使用这些方法,同时又希望不改变原数组,我们只能这样做:
const sorted1 = arr.slice().sort();
const sorted2 = [...arr].sort();
const sorted3 = Array.from(arr).sort();
这些方法的本质都是创建数组的副本,然后再更改这个副本。
新的无损方法
该提案引入了三种Array方法的无损版本:
-
.toReversed(): Array无损版本
.reverse() -
.toSorted(compareFn): Array无损版本
.sort() -
.toSpliced(start, deleteCount, ...items): Array无损版本
.splice()
同时该提案还引入了一个无损方法.with(),不过更方法没有对应破环版本。该方法的作用是无损的替换某个值(有点类似于arr[index]=value)
.toReversed(): Array
.toReversed() 是 .reverse()方法的无损版本:
const arr = ['a', 'b', 'c'];
assert.deepEqual(
arr.toReversed(), ['c', 'b', 'a']
);
assert.deepEqual(
arr, ['a', 'b', 'c']
);
.toReversed()方法的简单polyfill:
if (!Array.prototype.toReversed) {
Array.prototype.toReversed = function () {
return this.slice().reverse();
};
}
.toSorted(compareFn): Array
.toSorted() 是 .sort()方法的无损版本:
const arr = ['c', 'a', 'b'];
assert.deepEqual(
arr.toSorted(), ['a', 'b', 'c']
);
assert.deepEqual(
arr, ['c', 'a', 'b']
);
.toSorted()方法的简单polyfill:
if (!Array.prototype.toSorted) {
Array.prototype.toSorted = function (compareFn) {
return this.slice().sort(compareFn);
};
}
.toSpliced(start, deleteCount, ...items): Array
.toSpliced() 是 .splice()方法的无损版本。
const arr = ['a', 'b', 'c', 'd'];
assert.deepEqual(
arr.toSpliced(1, 2, 'X'), [ 'a', 'X', 'd' ]
);
assert.deepEqual(
arr, ['a', 'b', 'c', 'd']
);
.toSpliced()方法的简单polyfill:
if (!Array.prototype.toSpliced) {
Array.prototype.toSpliced = function (start, deleteCount, ...items) {
const copy = this.slice();
copy.splice(start, deleteCount, ...items);
return copy;
};
}
.with(index, value): Array
arr.with(index, value)是arr[index] = value的无损版本。以下代码说明了.with方法的运行过程:
const arr = ['a', 'b', 'c'];
assert.deepEqual(
arr.with(1, 'X'), ['a', 'X', 'c']
);
assert.deepEqual(
arr, ['a', 'b', 'c']
);
.with()方法的简单polyfill:
if (!Array.prototype.with) {
Array.prototype.with = function (index, value) {
const copy = this.slice();
copy[index] = value;
return copy;
};
}
总结
可以预见这几个新增的无损方法以后会提升程序员的编程效率,不过目前浏览器还没有支持,如果要使用,暂时还只能使用polyfill版本。