前言
拷貝也是面試經典吶!
數組的淺拷貝
如果是數組,我們可以利用數組的一些方法比如:slice、concat 返回一個新數組的特性來實現拷貝。
比如:
var arr = ['old', 1, true, null, undefined];
var new_arr = arr.concat();
new_arr[0] = 'new';
console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]
用 slice 可以這樣做:
var new_arr = arr.slice();
但是如果數組嵌套了對象或者數組的話,比如:
var arr = [{old: 'old'}, ['old']];
var new_arr = arr.concat();
arr[0].old = 'new';
arr[1][0] = 'new';
console.log(arr) // [{old: 'new'}, ['new']]
console.log(new_arr) // [{old: 'new'}, ['new']]
我們會發現,無論是新數組還是舊數組都發生了變化,也就是說使用 concat 方法,克隆的并不徹底。
如果數組元素是基本類型,就會拷貝一份,互不影響,而如果是對象或者數組,就會只拷貝對象和數組的引用,這樣我們無論在新舊數組進行了修改,兩者都會發生變化。
我們把這種復制引用的拷貝方法稱之為淺拷貝,與之對應的就是深拷貝,深拷貝就是指完全的拷貝一個對象,即使嵌套了對象,兩者也相互分離,修改一個對象的屬性,也不會影響另一個。
所以我們可以看出使用 concat 和 slice 是一種淺拷貝。
數組的深拷貝
那如何深拷貝一個數組呢?這里介紹一個技巧,不僅適用于數組還適用于對象!那就是:
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
var new_arr = JSON.parse( JSON.stringify(arr) );
console.log(new_arr);
是一個簡單粗暴的好方法,就是有一個問題,不能拷貝函數,我們做個試驗:
var arr = [function(){
console.log(a)
}, {
b: function(){
console.log(b)
}
}]
var new_arr = JSON.parse(JSON.stringify(arr));
console.log(new_arr);
我們會發現 new_arr 變成了:
使用,接下來我們思考下如何實現一個對象或者數組的淺拷貝。
想一想,好像很簡單,遍歷對象,然后把屬性和屬性值都放在一個新的對象不就好了~
嗯,就是這么簡單,注意幾個小點就可以了:
var shallowCopy = function(obj) {
// 只拷貝對象
if (typeof obj !== 'object') return;
// 根據obj的類型判斷是新建一個數組還是對象
var newObj = obj instanceof Array ? [] : {};
// 遍歷obj,并且判斷是obj的屬性才拷貝
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
深拷貝的實現
那如何實現一個深拷貝呢?說起來也好簡單,我們在拷貝的時候判斷一下屬性值的類型,如果是對象,我們遞歸調用深拷貝函數不就好了~
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
性能問題
盡管使用深拷貝會完全的克隆一個新對象,不會產生副作用,但是深拷貝因為使用遞歸,性能會不如淺拷貝,在開發中,還是要根據實際情況進行選擇。
下期預告
難道到這里就結束了?是的。然而本篇實際上是一個鋪墊,我們真正要看的是 jquery 的 extend 函數的實現,下一篇,我們會講一講如何從零實現一個 jquery 的 extend 函數。
作者:冴羽
github:https://github.com/mqyqingfeng/Blog
掘金主頁:https://juejin.im/user/58e4b9b261ff4b006b3227f4
segmentfault主頁:https://segmentfault.com/u/yayu/articles
Vicky丶Amor 經授權轉載,版權歸原作者所有。