物件的合併及拷貝

2021-09-12 22:16:09 字數 4719 閱讀 7782

object.assign()方法用於物件的合併,將所有自身的(非繼承的)可列舉屬性的值從乙個或多個源物件拷貝到目標物件。返回目標物件。目標物件自身也會改變。

object.assign(target, ...sources)
只拷貝源物件的自身屬性(不拷貝繼承屬性),也不拷貝不可列舉的屬性(enumerable: false)。

object.assign(,

object.defineproperty({}, 'invisible', )

)//

1. 只有乙個引數

如果只有乙個引數,object.assign()會直接返回該引數。

let obj = ;

object.assign(obj) === obj // true

如果該引數不是物件,則會先轉成物件,然後返回。

typeof object.assign(2) // "object"
由於undefinednull無法轉成物件,所以如果它們作為引數,就會報錯。

object.assign(undefined) // 報錯

object.assign(null) // 報錯

2. 物件 + 非物件

非物件引數都會轉成物件,如果無法轉成物件,就會跳過,不會報錯。

如果非物件引數為undefinednull,就會跳過,不會報錯,返回的依舊是目標物件引數。

let obj = ;

object.assign(obj, undefined) === obj // true

object.assign(obj, null) === obj // true

如果非物件引數為其他型別的值(即數值、字串和布林值),也不會報錯。但是,除了字串會以陣列形式拷貝入目標物件,其他值都不會產生效果。這是因為只有字串的包裝物件,會產生可列舉屬性。

let v1 = 'abc';

let v2 = true;

let v3 = 10;

let obj = object.assign({}, v1, v2, v3);

console.log(obj) //

3. 目標物件 + 源物件...

(1) 屬性值為nullundefined的屬性會正常合併

object.assign()不會跳過那些屬性值為nullundefined的源物件。

var o1 = ;

var o2 = ;

var obj = object.assign({}, o1, o2);

obj //

(2) 同名屬性的替換

如果目標物件與源物件中的屬性具有相同的鍵,則目標物件屬性將被源中的屬性覆蓋。後來的源的屬性將類似地覆蓋早先的屬性。

var o1 = ;

var o2 = ;

var o3 = ;

var obj = object.assign({}, o1, o2, o3);

obj //

(3) 淺拷貝

object.assign()方法實行的是淺拷貝,而不是深拷貝。拷貝的是屬性值。假如源物件的屬性值是乙個指向物件的引用,它也只拷貝那個引用值。

var obj1 =  };

var obj2 = object.assign({}, obj1);

obj2 // };

obj2.b.c = 3;

obj1 // };

obj2 // };

(4) 陣列的處理

object.assign()可以用來處理陣列,但是會把陣列視為鍵值為陣列下標的物件來合併,然而最終的返回形式也是陣列。

object.assign([1, 2, 3], [4, 5])  // [4, 5, 3]

object.assign(,) //

(5) 訪問器屬性的處理

object.assign()如果遇到訪問器定義的屬性,會只拷貝值。

var obj = 

};var copy = object.assign({}, obj);

copy //

因此必須使用object.getownpropertydescriptors()方法配合object.defineproperties()方法,就可以實現正確拷貝。但僅限於可拷貝gettersetter,對於屬性的引用型別還是屬於淺拷貝。

var obj = ,

get bar()

};var target = object.defineproperties({},

object.getownpropertydescriptors(obj)

);object.getownpropertydescriptor(target, 'bar')

//

obj.foo.a = 6

target.foo.a // 6

1. 為物件新增屬性
class point );

}}

上面方法通過object.assign()方法,將x屬性和y屬性新增到point類的物件例項。

2. 為物件新增方法

object.assign(someclass.prototype, ,

anothermethod()

});// 等同於下面的寫法

someclass.prototype.somemethod = function (arg1, arg2) ;

someclass.prototype.anothermethod = function () ;

3. 淺轉殖物件
let obj = ;

function clone(origin) , origin);

}let aaa = clone(obj); //

不過,採用這種方法轉殖,只能轉殖原始物件自身的值,不能轉殖它繼承的值。如果想要保持繼承鏈,可以採用下面的**。

function clone(origin)
4. 合併多個物件
let merge = (target, ...sources) => object.assign(target, ...sources);
如果希望合併後返回乙個新物件,可以改寫上面函式,對乙個空物件合併。

let merge = (...sources) => object.assign({}, ...sources);
5. 為屬性指定預設值
const defaults = ;

function copy(options) , defaults, options);

// ...

}

注意,由於存在淺拷貝的問題,defaults物件和options物件的所有屬性的值,最好都是簡單型別,不要指向另乙個物件。否則,defaults物件的該屬性很可能不起作用。

var obj1 = };

var obj2 = json.parse(json.stringify(obj1));

obj1.b.c = 4;

obj2 // }

但由於json的侷限性,該方法也不是萬能的。比如,如果物件的屬性是undefined、函式、symbolxml物件,該屬性會被json.stringify()過濾掉,導致拷貝時會缺少屬性。

let obj = 

}let cloneobj = json.parse(json.stringify(obj));

console.log(cloneobj); //

function deepclone(source); 

for(let keys in source);

targetobj[keys] = deepclone(source[keys]);

}else

}} return targetobj;

}let obj = , sayhello: function() }

let cloneobj = deepclone(obj);

obj.a.b = 4

obj // ,sayhello:ƒ ()}

cloneobj // ,sayhello:ƒ ()}

js深度物件合併,深度賦值 拷貝

平時我們在處理純粹物件 鍵值對物件 json 時,如果使用object.assign或者物件解構賦值,只會合併第一層的資料,而當合併巢狀物件,將會直接覆蓋掉前面被合併物件裡的資料,這是因為object.assign和物件解構賦值都是只有第一層屬於深拷貝,而往下都是淺拷貝,例如 var obj1 va...

js陣列及物件的深拷貝

var arr1 1,2,3 var arr2 arr1.slice 0 arr1 0 0 console.log arr1 console.log arr2 var arr3 1,2,3 var arr4 arr3.concat arr3 0 0 console.log arr3 console....

javascript中陣列及物件的合併

1 陣列遍曆法 var arr1 1,2,3,4 var arr2 2,3,4,5 type 1 for var i 0 i arr1.length i console.log arr2 2,3,4,5,1,2,3,4 type 2 for var item of arr1 2 concat方法 v...