Object.assign()的基本使用 && 语法
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象,他返回目标对象
- 参数:target 目标对象,source 源对象
- 返回值:目标对象
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(target === returnedTarget) // true
问题1: 返回值是目标对象吗?
下面代码很好地回答了这个问题
console.log(target === returnedTarget) // true
问题2:参数为非对象会发生什么?
(1)目标对象为null或者undefined
直接报错,说明目标对象不能为null或者undefined
(2)源对象中有null或者undefined
从打印结果来看,null
和undefined
被忽略了
(3)源对象中有boolean,number, string, 数组怎么处理?
从打印结果看,boolean number string都被忽略了,而数组则转换为了‘index’:value
的形式
这是为什么呢?这是因为检索到源对象中含有非数组的值的时候,会先用Object对这些值进行包装,
我们看数组
被包装后的样子:
console.log(Object.getOwnPropertyDescriptors(Object([1,2,3])));
/**
* {
'0': { value: 1, writable: true, enumerable: true, configurable: true },
'1': { value: 2, writable: true, enumerable: true, configurable: true },
'2': { value: 3, writable: true, enumerable: true, configurable: true },
length: { value: 3, writable: true, enumerable: false, configurable: false }
}
* **/
而number则为
console.log(Object(123)); // [Number: 123]
console.log(Object.getOwnPropertyDescriptors(Object(123))); // {}
问题3: 继承属性和不可枚举属性是不能拷贝的
看下面这个例子:
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const obj = Object.create({foo:1}, {
bar:{
value:'hello', // 不可枚举
},
baz:{
value:'hi',
enumerable: true, // 可枚举
},
});
console.log(obj);
const returnedTarget = Object.assign(target, obj);
console.log(returnedTarget);
在这个例子中,我们使用Object.create()
创建了obj
, 其中{foo:1}
是新建对象obj
的原型,bar
不可枚举,而baz
可枚举,我们将obj
作为源对象assign
给目标对象target
的时候,返回的结果为:
说明:继承属性和不可枚举属性是不能拷贝的
问题4:Object.assign()是浅拷贝还是深拷贝?
当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝
(1)一级属性
let obj1 = {
name:'Katrina',
age:18,
};
let obj2 = Object.assign({}, obj1);
console.log(obj1, obj2); // obj1 = { name: 'Katrina', age: 18 } obj2 = { name: 'Katrina', age: 18 }
obj1.name = 'Jack'; // 修改obj1中的name
console.log(obj1, obj2); // obj2未发生改变 obj1 = { name: 'Jack', age: 18 } obj2 = { name: 'Katrina', age: 18 }
(2)二级属性
let obj1 = {
name:'Katrina',
age:18,
family:{
father:'Jack',
mother:'Mary',
}
};
let obj2 = Object.assign({}, obj1);
console.log(obj1, obj2);
// obj1 = { name: 'Katrina', age: 18, family: { father: 'Jack', mother: 'Mary' } } obj2 = { name: 'Katrina', age: 18, family: { father: 'Jack', mother: 'Mary' } }
obj1.family.father = 'KK'; // 修改family中的father
console.log(obj1, obj2); // obj2发生改变
// obj1 = { name: 'Katrina', age: 18, family: { father: 'KK', mother: 'Mary' } } obj2 = { name: 'Katrina', age: 18, family: { father: 'KK', mother: 'Mary' } }
问题5:合并同对象有同属性怎么变化?
let obj1 = {
name:'Katrina',
age:18,
};
let obj2 = {
name:'Jack',
age:19,
gender:'Female',
};
let obj3 = Object.assign(obj2, obj1);
console.log(obj3); // { name: 'Katrina', age: 18, gender: 'Female' }
显然是发生了替换
问题6:异常会打断后续拷贝任务
const target = Object.defineProperty({}, "foo", {
value: 1,
writable: false
}); // target 的 foo 属性是个只读属性。
Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。
console.log(target.bar); // 2,说明第一个源对象拷贝成功了。
console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。
console.log(target.foo); // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。
console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。
console.log(target.baz); // undefined,第三个源对象更是不会被拷贝到的。