Object.assign
方法只会拷贝源对象自身属性(不复制继承属性),也不复制不可枚举的属性(enumerable: false)。该方法使用源对象的[[Get]]
和目标对象的[[Set]]
,所以它会调用相关 getter 和 setter。
Object.assign()
函数会触发 setters,而展开语法则不会。
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
console.log(obj1); // { foo: 'bar', x: 42 };
console.log(mergedObj); // { foo: "baz", x: 42, y: 13 }
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
扩展运算符和Object.assign是深拷贝还是浅拷贝
扩展运算符
// 对象只有一级数据,是深拷贝
var obj1 = { foo: 'bar', x: 42 };
var clonedObj = { ...obj1 };
//console.log(clonedObj); // 克隆后的对象: { foo: "bar", x: 42 }
clonedObj.x = 30;
console.log(clonedObj); // { foo: "bar", x: 30 }
console.log(obj1); // { foo: "bar", x: 42 }
// 对象有两层数据及以上,是浅拷贝
var obj2 = {
foo: 'baz',
y: 13 ,
su: {
name: 'mars'
}
};
var clonedObj = { ...obj2 };
clonedObj.su.name = 'kyire';
console.log(clonedObj);
console.log(obj2);
// 打印出的obj2和cloneObj都一样
{
foo: 'baz',
y: 13 ,
su: {
name: 'kyire'
}
}
Object.assign
对象只有一层数据,是深拷贝。两层及以上是浅拷贝
var obj2 = {
foo: 'baz',
y: 13 ,
su: {
name: 'mars'
}
};
var clonedObj = Object.assign({}, obj2);
clonedObj.y = 89;
clonedObj.su.name = 'kyire';
console.log(clonedObj);
{
foo: 'baz',
y: 89 ,
su: {
name: 'kyire'
}
}
console.log(obj2);
{
foo: 'baz',
y: 13 ,
su: {
name: 'kyire'
}
}
性能比对
Object.assign对象拷贝时速度更快
function testObject(){
let result = {};
console.time('A');
for(let i=0;i<2000;i++){
result = {...result, ['key' + i]: i };
}
console.timeEnd('A');
}
testObject();
// A: 555.3701171875 ms
function testObject(){
let result = {};
console.time('A');
for(let i=0;i<2000;i++){
result = Object.assign(result, {['key' + i]: i});
}
console.timeEnd('A');
}
testObject();// A: 5.806884765625 ms