热搜:fiddler git ip ios 代理
历史搜索

32. ES6+ Object.assign()方法

游客2024-09-27 07:53:01
目录文章目录
  1. 1. 前言
  2. 2. 方法详情
  3. 3. 浅拷贝
  4. 4. 基本类型的合并
  5. 5. 拷贝异常时会被打断
  6. 6. 小结

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() 属于浅拷贝;
  • 合并对象时后面的对象会覆盖前面的对象;
  • 拷贝时发生异常,前面已拷贝的不会受到影响,异常后面的对象则不会被拷贝。
标签:ES6