編寫一個物件&&陣列深copy函式方法

混沌傳奇發表於2018-02-24

介紹

什麼是深copy?意思就是指源物件與拷貝物件互相獨立,其中任何一個物件的改動都不會對另外一個物件造成影響。舉個例子,一個人名叫張三,後來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三以後缺胳膊少腿還是李四以後掛掉了,都不會影響另外一個人。

在js中,深copy一個物件,不論源物件或者拷貝物件改變,都不會對物件造成影響,舉個js的栗子:

//我們定義了一個張三,然後又用deepCopy基於張三深拷貝了一個名字為李四的人。
var people1 = {name: '張三', age: 20, die: false, hobbies: ['旅遊', '打籃球']};
var people2 = deepCopy(people1);
people2.name = '李四';

//列印people1和people2的name
console.log('people1:', people1.name, 'people2:', people2.name); //people1: 張三   people2: 李四

//我們再修改people2的興趣愛好(hobbies)
people2.hobbies[1] = '看書';
console.log('李四的愛好是:', people2.hobbies); //李四的愛好是:["旅遊", "看書"]
console.log('張三的愛好是:', people1.hobbies); //張三的愛好是:["旅遊", "打籃球"]
複製程式碼

從上面的程式碼執行過程和結果我們看到,用深拷貝方法拷貝的新物件和源物件是互相不影響的。

目的

編寫一個能夠深copy陣列和物件的js函式方法

程式碼

function deepCopy(obj) {
    var newObj;
    if(typeof obj === 'object'){
        newObj = obj.constructor === Array ? [] : {};
        for(var key in obj){
            if(typeof obj[key] === 'object'){
                newObj[key] = deepCopy(obj[key]);
            }else{
                newObj[key] = obj[key];
            }
        }
    }else{
        newObj = obj;
    }
    return newObj;
}
複製程式碼

講解

上面程式碼中deepCopy函式的實現過程中,可以看到用到了函式遞迴。這裡用函式遞迴是為了解決物件中的屬性為陣列或者物件時,深層拷貝的陣列||物件屬性。還有一個判斷陣列和物件的方法,我這裡用的是 obj.constructor === Array ? [] : {},因為陣列也屬於物件,所以用typeof無法區分陣列和物件。當然還有很多種其他的區分陣列和物件的方法了,大家可以在編寫自己的deepCopy方法的時候使用。

說下淺複製和深複製的區別:

淺複製:只會將物件的各個屬性進行依次複製,並不會進行遞迴複製,而js儲存物件都是存地址的,所以淺複製會導致源物件的物件||陣列屬性和拷貝物件的物件||陣列屬性 指向同一塊記憶體地址;會導致引用。

深複製:它不僅將原物件的各個屬性逐個複製出去,而且將原物件各個屬性所包含的物件也依次採用深複製的方法遞迴複製到新物件上。這就不會存在屬性指向同一個物件||陣列的問題。

相關文章