1. 前言
Object 对象的更新 把一个对象复制到另一个对象,在 ES5 中需要循环对象进行拷贝。
2. 方法详情
2.1 基本语法
语法使用:
Object.assign(target, ...sources)
参数解释:
参数 | 描述 |
---|---|
target | 需要拷贝到的目标对象 |
sources | 源对象 |
2.2 拷贝对象
let target = {}; let source = {a: 1, b: 2, c: 3}; Object.assign(target, source); target.d = 4; console.log(target) // {a: 1, b: 2, c: 3, d: 4} console.log(source) // {a: 1, b: 2, c: 3}
上面的代码可以看出,Object.assign()
的主要用法就是把源对象拷贝到指定的对象上去,目标对象的更改不会影响源对象。
2.3 合并对象
let target = {a: 1}; let source1 = {b: 2}; let source2 = {c: 3}; Object.assign(target, source1, source2); console.log(target); // {a: 1, b: 2, c: 3}
上面的代码可以看出,Object.assign()
不会把目标对象清空,会合并后面所有的对象上的值。
2.4 覆盖前面的值
let target = {a: 1, b: 1}; let source1 = {b: 2, c: 2}; let source2 = {c: 3}; Object.assign(target, source1, source2); console.log(target); // {a: 1, b: 2, c: 3}
如果后面的源对象上有相同的值,后面的源对象会覆盖前面对象上的值,这一点需要注意。
3. 浅拷贝
Object.assign()
的拷贝属于浅拷贝,也就是说它只拷贝对下的第一层的属性值。如果这个值是一个对象类型,那么 Object.assign()
不会对该对象进行深拷贝,也就是说,拷贝后的对象下的这个对象类型是源对象和拷贝后的对象共有的,无论谁(源对象或拷贝后对象)对这个对象下的值进行修改,另一个对象(源对象或拷贝后对象)也会共享这个改变。看下面的例子更清晰的表达:
var target = {}; var source = {a: 1, b: {c: 2, d: 3}}; Object.assign(target, source); target.a = 5; target.b.c = 9; console.log(target) // {a: 5, b: {c: 9, d: 3}} console.log(source) // {a: 1, b: {c: 9, d: 3}}
上面的代码中,源对象 source 是个两层的字面量对象,b 也是一个对象。使用 Object.assign()
拷贝给目标对象 target,拷贝后对 target 对象下的值进行修改,然后打印目标对象和源对象。从打印的结果可以看出,对 target 第一层的 a 进行修改时,源对象是不会改变。但是对 target 下的 b 对象下的值进行修改时,因为 b 也是一个对象,所以源对象中的值也被修改了。到这里可以看出,Object.assign()
没有对 b 进行拷贝。
如果需要深拷贝则需要,需要递归地使用去 Object.assign()
来拷贝对象。
4. 基本类型的合并
当合并的源对象是基本类型时,这些基本类型会作为最后对象上的值,而键则以数字递增,其中如果值是 null 和 undefined 时会被忽略。看如下实例:
var s1 = "abc"; var s2 = true; var s3 = 10; var s4 = Symbol("foo") var obj = Object.assign({}, s1, null, s2, undefined, s3, s4); console.log(obj); // { "0": "a", "1": "b", "2": "c" }
5. 拷贝异常时会被打断
在拷贝时如果发生异常,则拷贝会被终止,并报错,前面已经被拷贝的不会被影响可以继续使用,但后面没有被拷贝的则不能被使用。
var target = Object.defineProperty({}, "a", { value: 1, writable: false }); Object.assign(target, {b: 2}, {a: 3}, {c: 4}); // Uncaught TypeError: Cannot assign to read only property 'a' of object ' console.log(target.b); // 2 console.log(target.c); // undefined
上面的代码中,定义了目标对象 target 上的属性 a 是只读的,也就是不能不被修改,在合并代码时,源对象上有 a,则报了 a 是对象上的只读属性不能被 assign 操作。从后面的打印结果可以看出,b 已经被拷贝到目标对象上了可以正常使用,但由于拷贝中发生异常,最后一个对象没有被拷贝,所以 c 的值是 undefined。
6. 小结
本章讲解了用于合并对象的方法 Object.assign()
主要有以下几点需要注意的。
Object.assign()
属于浅拷贝;- 合并对象时后面的对象会覆盖前面的对象;
- 拷贝时发生异常,前面已拷贝的不会受到影响,异常后面的对象则不会被拷贝。