Object.assign在一种情况下创建深层副本,而在另一种情况下仅创建浅层副本

时间:2018-07-27 12:14:03

标签: javascript

因此,我知道Object.assign仅制作对象的浅表副本。但是为什么在第二个console.log()中却给了我与新对象合并的完整深层副本?

我不明白...

const initialState1 = {
  boot: {
    items: [],
    pos: {},
    crType: [
      {
        additionalInfo: {
          blankCDs: 90
        },
        requirements: {
          items: [
            {
              count: 0
            },
            {}
          ]
        }
      },
      {},
      {}
    ],
    toggleDispatch: () => {},
    showSelector: false,
  }
}

const showPopup = {
  boot: {
    showSelector: true
  }
}

console.log(Object.assign(initialState1, showPopup))


const initialState2 = {
  callback: () => {},
  itemId: 0,
  lastSubID: 0,
  close: () => {},
  current: 0,
  state: '',
  isShopComplete: false,
  requirements: {
    minLevel: {
      available: false
    }
  }
}


 const educ = {
  requirements: {
    minLevel: {
      available: true
    }
  }
}


console.log(Object.assign(initialState2, educ))

2 个答案:

答案 0 :(得分:3)

在两种情况下,后一个对象中的顶级属性都分配给前一个对象中的相同属性。即:

Object.assign({ foo: 'bar' }, { foo: 'baz' })

这最终以{ foo: 'baz' }结尾,因为来自第二个对象的键foo的值已分配给第一个对象的属性foo

{                   {
  foo: 'bar'  <---    foo: 'baz'
}                   }

所以它也发生在您的两个对象中:

{                                      {
  boot: {                   <----        boot: {
    items: [],              <----          showSelector: true
    pos: {},                <----        }
    crType: [...],                     }
    toggleDispatch: () => {},
    showSelector: false,
  }
}

只有一个顶级属性boot被覆盖,但是在这种情况下,这几乎就是您的整个对象。

{
  callback: () => {},
  itemId: 0,
  lastSubID: 0,
  close: () => {},
  current: 0,
  state: '',
  isShopComplete: false,           {
  requirements: {         <----      requirements: {
    minLevel: {           <----        minLevel: {
      available: false    <----          available: true
    }                     <----        }
  }                       <----      }
}                                  }

只有一个顶级属性被覆盖,但还有更多属性在第二个对象中没有等效的对等项,它们保持原样。

答案 1 :(得分:2)

在两种情况下,它都会创建浅表副本。您需要了解,浅表副本并不意味着对象深度为1,而是键值对包含对同一对象的引用,而不是副本。

也就是说,如果更改内部对象的属性,它将反映在原始对象中。在第一种情况下,如果更改了showSelector方法返回的对象的Object.assign属性,它将反映在showPopup对象上。这就是浅表副本的意思。

在第二种情况下,如果更改requirements.minLevel属性,它也会反映在educ对象上。