[ES6]Object.assign() | 青训营

102 阅读2分钟

[ES6]Object.assign()

MDN:

Object.assign()  静态方法将一个或者多个源对象中所有可枚举自有属性复制到目标对象,并返回修改后的目标对象。

语法:

  Object.assign(target, ...sources)

示例:

  let searchParmas = {
  categoryId: '',
  categoryName: '',
  keyword: '',
  props: [],
  trademark: '',
  order: '',
  pageNo: 1,
  pageSize: 10,
  };
  let query = { categoryName: '衣服', categoryId: '11', pageNo: '1'};
  let params = { keyword: 'T恤', pageNo: '10' };
  console.log(Object.assign(searchParmas, query, params));

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

打印结果为:

  
  {
      "categoryId": "11",
      "categoryName": "衣服",
      "keyword": "T恤",
      "props": [],
      "trademark": "",
      "order": "",
      "pageNo": 10,
      "pageSize": 10
  }

如果只有一个参数,Object.assign会直接返回该参数。

  const obj = {a: 1}
  ​
  Object.assign(obj) // {a: 1}
  Object.assign(obj) === obj // true

如果该参数不是对象,则会先转成对象,然后返回。

  typeof Object.assign(2) // "object"

由于undefinednull无法转成对象,所以如果它们作为参数,就会报错。

  Object.assign(undefined) // 报错
  Object.assign(null) // 报错

如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefinednull不在首参数,就不会报错。

  let obj = {a: 1}
  Object.assign(obj, undefined) === obj // true
  Object.assign(obj, null) === obj // true

注意:

浅拷贝

Object.assign方法实行的是浅拷贝,而不是深拷贝

如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用,这个对象的任何变化,都会反映到目标对象上面

  const obj1 = {a: {b: 1}}
  const obj2 = Object.assign({}, obj1)
  ​
  obj1.a.b = 2
  console.log(obj2)

打印结果:{"a": {"b": 2}}

同名替换

对于嵌套的对象,遇到同名属性,Object.assign的处理方法是替换

  const target = { a: { b: 'c', d: 'e' } }
  const source = { a: { b: 'hello' } }
  ​
  console.log(Object.assign(target, source))

打印结果:{"a":{"b":2}}

上面代码中,target对象的a属性被source对象的a属性整个替换掉了,而不会得到{ a: { b: 'hello', d: 'e' } }的结果。这通常不是开发者想要的,需要特别小心。

一些函数库提供 Object.assign的定制版本(比如 Lodash_.defaultsDeep方法),可以得到深拷贝的合并。

数组的处理

Object.assign可以用来处理数组,但是会把数组视为对象

  console.log(Object.assign([1, 2, 3]))
  console.log(Object.assign([1, 2, 3], [4, 5]))

[ 1, 2, 3 ]

[ 4, 5, 3 ]

Object.assign把数组视为属性名为0、1、2 的对象,因此源数组的0号属性4覆盖了目标数组的0号属性1

取值函数的处理

Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制

  const source = {
    get foo() { return 1 }
  }
  const target = {}
  ​
  console.log(Object.assign(target, source))

{"foo": 1}

source对象的foo属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值复制过去

引用: saerankk juejin.cn/post/684490…