Array複製方法總結 | |||
---|---|---|---|
Array.slice(淺拷貝) | for() 、while | map、 filter | |
Array.cancat | Array.reduce() | Object.assign() Es6 | |
擴展運算符 Es6 | Array.from()Es6 | JSON.parse(JSON.stringify()) |
ES5 Array複製方法總結
1.Array.slice(淺拷貝)
slice 方法根據我們指定的start、end的index從原數組中返回一個淺拷貝的數組。
[1, 2, 3, 4, 5].slice(0, 3);
// [1, 2, 3]
// Starts at index 0, stops at index 3
// 當不給定參數時,就返回了原數組的拷貝
同樣的,處理對象和數組的時候是引用而不是值複製
2. 遍歷複製數組:for() 、while、map、 filter、 reduce
for()循環(淺拷貝) *
考慮到函數式編程變得越來越流行,我認爲這種方法可能是最不受歡迎的。
let numbers = [1, 2, 3];
let numbersCopy = [];
for (let i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
這個方法不能有效的拷貝多維數組。
while()循環(淺拷貝)
numbers = [1, 2, 3];
numbersCopy = [];
i = -1;
while (++i < numbers.length) {
numbersCopy[i] = numbers[i];
}
Array.map(淺拷貝)
當我們使用map方法時,需要給出一個callback函數用於處理當前的數組,並返回一個新的數組元素。
同樣的,處理對象和數組的時候是引用而不是值複製。
Array.filter(淺拷貝)
Array.filter方法同樣會返回一個新數組,但是並不一定是返回同樣長度的,這和我們的過濾條件有關。
同樣的,處理對象和數組的時候是引用而不是值複製。
Array.reduce(淺拷貝)
其實用reduce來拷貝數組並沒有展示出它的實際功能,但是我們還是要將其能夠拷貝數組的能力說一下的
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);
reduce() 方法對數組中的每個元素執行一個由您提供的reducer函數,將其結果彙總爲單個返回值。
同樣的,處理對象和數組的時候是引用而不是值複製。
3、Array.cancat(淺拷貝)
concat將數組與值或其他數組進行組合。
[1, 2, 3].concat(4); // [1, 2, 3, 4]
如果我們不指定參數或者提供一個空數組作爲參數,就可以進行淺拷貝。
同樣的,處理對象和數組的時候是引用而不是值複製。
ES6 方法總結
1. Object.assign() 淺拷貝
Object.assign() 方法用於將所有可枚舉屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
2. 擴展運算符(淺拷貝)
這個方法不能有效的拷貝多維數組。數組/對象值的拷貝是通過引用而不是值複製。
3、Array.from(淺拷貝)
可以將任何可迭代對象轉換爲數組。給一個數組返回一個淺拷貝。
同樣的,處理對象和數組的時候是引用而不是值複製。
JSON.parse & JSON.stringify(深拷貝)
JSON.stringify將一個對象轉成字符串;
JSON.parse將轉成的字符串轉回對象。
將它們組合起來可以將對象轉換成字符串,然後反轉這個過程來創建一個全新的數據結構。
nestedNumbers = [[1], [2]];
numbersCopy = JSON.parse(
JSON.stringify(nestedNumbers)
);
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1], [2]]
// [[1, 300], [2]]
這個可以安全地拷貝深度嵌套的對象/數組
幾種特殊情況
1、如果obj裏面有時間對象,則JSON.stringify後再JSON.parse的結果,時間將只是字符串的形式。而不是時間對象;
var test = {
name: 'a',
date: [new Date(1536627600000), new Date(1540047600000)],
};
let = JSON.parse(JSON.stringify(test))
2、如果obj裏有RegExp、Error對象,則序列化的結果將只得到空對象;
const test = {
name: 'a',
date: new RegExp('\\w+'),
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
3、如果obj裏有函數,undefined,則序列化的結果會把函數或 undefined丟失;
const test = {
name: 'a',
date: function hehe() {
console.log('fff')
},
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.error('ddd', test, copyed)
4、如果obj裏有NaN、Infinity和-Infinity,則序列化的結果會變成null
5、JSON.stringify()只能序列化對象的可枚舉的自有屬性,
例如 如果obj中的對象是有構造函數生成的, 則使用JSON.parse(JSON.stringify(obj))深拷貝後,會丟棄對象的constructor;
function Person(name) {
this.name = name;
}
const liai = new Person('liai');
const test = {
name: 'a',
date: liai,
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'