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"
由於undefined
和null
無法轉成物件,所以如果它們作為引數,就會報錯。
object.assign(undefined) // 報錯
object.assign(null) // 報錯
2. 物件 + 非物件
非物件引數都會轉成物件,如果無法轉成物件,就會跳過,不會報錯。
如果非物件引數為undefined
和null
,就會跳過,不會報錯,返回的依舊是目標物件引數。
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) 屬性值為null
或undefined
的屬性會正常合併
object.assign()
不會跳過那些屬性值為null
或undefined
的源物件。
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()
方法,就可以實現正確拷貝。但僅限於可拷貝getter
和setter
,對於屬性的引用型別還是屬於淺拷貝。
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
、函式、symbol
或xml
物件,該屬性會被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...