JavaScript 數(shù)組新增四個(gè)非破壞性方法!
今天聊 JavaScript 的最新提案。開門見山,JavaScript 數(shù)組即將新增四個(gè)新的非破壞性方法:
- toReversed()
- toSorted()
- toSpliced()
- with()
Change Array by copy 提案

這四個(gè)方法來源于新的 Change Array by copy 提案,目前已經(jīng)處于 stage3階段,意味著基本上不會(huì)再有太大變化了,我們即將在各大瀏覽器里看到它們的實(shí)現(xiàn)。
提案地址:https://github.com/tc39/proposal-change-array-by-copy
數(shù)組的破壞性和非破壞性
為啥這個(gè)提案叫 Change Array by copy 呢?字面意思就是從副本里改變數(shù)組。
這就要說起數(shù)組的破壞性和非破壞性方法了:
有些數(shù)組的方法我們?cè)谡{(diào)用的時(shí)候不會(huì)改變?cè)嫉臄?shù)組,我們稱它們?yōu)榉瞧茐男苑椒?,比如我們?jīng)常用到的 filter、some、map、find 等方法,斗是不會(huì)改變?cè)瓟?shù)組的:
但是,另外有一些方法是會(huì)改變?cè)瓟?shù)組本身的,比如:sort、reverse、splice 等方法。
可以看到,原數(shù)組和排序后得到的新數(shù)組是一樣的,說明這個(gè)方法改變了原數(shù)組。很多時(shí)候我們想用這些方法,但是又不想改變?cè)瓟?shù)組,我們可能會(huì)先創(chuàng)建一個(gè)副本,比如下面這些操作:
const sorted1 = array1.slice().sort();
const sorted2 = [array1].sort();
const sorted3 = Array.from(array1).sort();
幾個(gè)數(shù)組的新方法,就是用來解決這樣的問題的。
toSorted()
.toSorted() 是 .sort() 的非破壞性版本:
const array = ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i'];
const result = array.toSorted();
console.log(result); // ['a', 'c', 'd', 'i', 'l', 'n', 'o', 'r']
console.log(array); // ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i']
下面是個(gè)簡(jiǎn)單的 polyfill:
if (!Array.prototype.toSorted) {
Array.prototype.toSorted = function (compareFn) {
return this.slice().sort(compareFn);
};
}
toReversed()
.toReversed() 是 .reverse() 的非破壞性版本:
const array = ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i'];
const result = array.toReversed();
console.log(result); // ['i', 'l', 'd', 'r', 'a', 'n', 'o', 'c']
console.log(array); // ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i']
下面是個(gè)簡(jiǎn)單的 polyfill:
if (!Array.prototype.toReversed) {
Array.prototype.toReversed = function () {
return this.slice().reverse();
};
}
with()
with() 是對(duì)數(shù)組的某個(gè)元素賦值操作的非破壞性版本,比如下面的操作:
array[index] = value
如果我們只是想得到一個(gè)新數(shù)組,又不想改變?cè)瓟?shù)組,可以這樣用:
const array = ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i'];
const result = array.with(0, 'ConardLi')
console.log(result); // ['ConardLi', 'o', 'n', 'a', 'r', 'd', 'l', 'i'];
console.log(array); // ['c', 'o', 'n', 'a', 'r', 'd', 'l', 'i']
下面是個(gè)簡(jiǎn)單的 polyfill:
if (!Array.prototype.with) {
Array.prototype.with = function (index, value) {
const copy = this.slice();
copy[index] = value;
return copy;
};
}
toSpliced()
.splice(start, deleteCount, ...items) 方法比其他幾個(gè)破壞性方法更復(fù)雜點(diǎn):
- 它從 start 開始刪除 deleteCount 個(gè)元素 ;
- 然后把 items 插入到被刪除的位置;
- 最后返回已刪除的元素。
const array = [1, 2, 3, 4, 5, 6];
const result = array.splice(1, 2, 0);
console.log(result); // [2, 3]
console.log(array); // [1, 0, 4, 5, 6]
.tospliced() 是 .splice() 的非破壞性版本,它會(huì)返回原數(shù)組變更后的版本,因此我們拿不到被刪除的元素:
const array = [1, 2, 3, 4, 5, 6];
const result = array.tospliced(1, 2, 0);
console.log(result); // [1, 0, 4, 5, 6]
console.log(array); // [1, 2, 3, 4, 5, 6]
下面是個(gè)簡(jiǎn)單的 polyfill:
if (!Array.prototype.toSpliced) {
Array.prototype.toSpliced = function (start, deleteCount, items) {
const copy = this.slice();
copy.splice(start, deleteCount, items);
return copy;
};
}
polyfill提案目前還在 stage3階段,在生產(chǎn)使用最好使用 polyfill:
https://github.com/tc39/proposal-change-array-by-copy/blob/main/polyfill.js