1. 程式人生 > >JS物件的引用,物件的拷貝

JS物件的引用,物件的拷貝

一、場景

除了基本型別跟null,物件之間的賦值,只是將地址指向同一個,而不是真正意義上的拷貝

將一個物件賦值給另外一個物件。

var a = [1,2,3];
var b = a;
b.push(4); // b中添加了一個4
alert(a); // a變成了[1,2,3,4]  

自定義物件

var obj = {a:10};
var obj2 = obj;
obj2.a = 20; // obj2.a改變了,
alert(obj.a); // 20,obj的a跟著改變  

這就是由於物件型別直接賦值,只是將引用指向同一個地址,導致修改了obj會導致obj2也被修改

二、淺拷貝

所以,我們需要封裝一個函式,來對物件進行拷貝,通過for in 迴圈獲取基本型別,賦值每一個基本型別,才能真正意義上的複製一個物件

var obj = {a:10};
function copy(obj){
    var newobj = {};
    for ( var attr in obj) {
        newobj[attr] = obj[attr];
    }
    return newobj;
}
var obj2 = copy(obj);
obj2.a = 20;
alert(obj.a); //10  

這樣就解決了物件賦值的問題。

 

三、深拷貝

但是這裡存在隱患,如果obj中,a的值不是10,而是一個物件,這樣就會導致在for in中,將a這個物件的引用賦值為新物件,導致存在物件引用的問題。

var obj = {a:{b:10}};
function copy(obj){
    var newobj = {};
    for ( var attr in obj) {
        newobj[attr] = obj[attr];
    }
    return newobj;
}
var obj2 = copy(obj);
obj2.a.b = 20;
alert(obj.a.b); //20  

因此,由於這個copy物件只是對第一層進行拷貝,無法拷貝深層的物件,這個copy為淺拷貝,我們需要通過遞迴,來拷貝深層的物件。將copy改造成遞迴即可

var obj = {a:{b:10}};
function deepCopy(obj){
    if(typeof obj != 'object'){
        return obj;
    }
    var newobj = {};
    for ( var attr in obj) {
        newobj[attr] = deepCopy(obj[attr]);
    }
    return newobj;
}
var obj2 = deepCopy(obj);
obj2.a.b = 20;
alert(obj.a.b); //10  

//當然利用 Object.assign 也能解決

 

 

2.  JSON物件形式亦闊以處理

let params = JSON.parse(JSON.stringify(this.form)); 

3.es6 的 Object.assign 

let obj = {a:1,b:2},obj2={}
Object.assign(obj2,obj)
console.log(obj2) // {a:1,b:2}
console.log(obj2 == obj) // false

//Object.assign 只能做淺拷貝之用 也就是說 只能拷貝一層

4.es6 的解構方法 

let obj = {a:1,b:2}
let obj1 = {...obj}
console.log(obj1) // {a:1,b:2}
console.log(obj == obj1) //false


let aa = {a:1,b:{c:11}}
let bb = {...aa}
bb.b.c = 22
console.log(aa.b.c) // 22
console.log(bb) // {a:1,b:{c:22}}
console.log(aa == bb) // false 

//也只能拷貝一層之用