繁体   English   中英

Object.assign和对象传播之间的区别(使用[…]语法)?

[英]Difference between Object.assign and object spread (using […] syntax)?

我在这里有一些代码,我想知道这是同一件事还是不同。 我很确定这两个都应该是相同的,但是我不确定自己是否做对了。

let zoneComment = updatedMap[action.comment.zone]
        ? [...updatedMap[action.comment.zone]] : [];

let zoneComment = updatedMap[action.comment.zone]
          ? Object.assign([], updatedMap[action.comment.zone]) : [];

如果这些相同,那我应该使用哪个呢? 我想使用最佳做法,因此,如果您的意见更好,请声明。

在您的特定情况下,他们是一样的。

原因是您拥有一个数组,而不是一个对象。

在数组上执行...将散布数组中的所有元素(但不包括属性)

Object.assign需要一个对象,因此它将数组视为对象并将所有可枚举的自身属性复制到其中,而不仅仅是元素:

 const a = [1, 2, 3]; a.test = 'example'; const one = [...a] // [1, 2, 3]; const two = Object.assign([], a); // { '0': 1, '1': 2, '2': 3, 'test': 'example' } console.log('\\none'); for (let prop in one) { console.log(prop); } console.log('\\ntwo'); for (let prop in two) { console.log(prop); } 


但是,如果将应用于对象的...运算符与Object.assign ,则它们实际上是相同的:

 // same result const a = { name: 'test' } console.log({ ...a }) console.log(Object.assign({}, a)) 

除了...总是创建一个新对象,但是Object.assign也允许您更改现有对象。

 // same result const a = { name: 'test' } const b = { ...a, name: 'change' }; console.log(a.name); // test Object.assign(a, { name: 'change'}) console.log(a.name); // change 

请记住, Object.assign已经是语言的一部分,而对象传播仍然只是一个建议,并且需要使用babel之类的工具进行预处理(编译)步骤。

您的问题真的可以归结为:

arr是数组时Object.assign([], arr) [...arr]Object.assign([], arr)提供相同的结果?

答案是:通常是,但是:

  • 如果arr是一个最后一个槽没有值的稀疏数组,则两种情况下结果的length属性将不同:spread语法将为length属性保持相同的值,但是Object.assign将产生一个length与上次使用的插槽的索引相对应的数组,再加上一个。

  • 如果arr是一个稀疏数组(如Array(10)得到的那样),则传播语法将创建一个在这些索引处具有undefined值的数组,因此它将不是稀疏数组。 另一方面, Object.assign将真正使这些插槽为空(不存在)。

  • 如果arr具有自定义的可枚举属性,则它们将由Object.assign复制,但不会由传播语法复制。

以下是这些差异的前两个示例:

 var arr = ["abc"] arr[2] = "def"; // leave slot 1 empty arr.length = 4; // empty slot at index 3 var a = [...arr]; var b = Object.assign([], arr); console.log(a.length, a instanceof Array); // 4, true console.log(b.length, b instanceof Array); // 3, true console.log('1' in arr); // false console.log('1' in a); // true (undefined) console.log('1' in b); // false 

但是,如果arr是一个标准数组(没有额外的属性),并且所有插槽都已填充,则两种方法都会产生相同的结果:

两者都返回一个数组。 [...arr]按照定义执行此操作,而Object.assign则执行此操作,因为它的第一个参数是一个数组,并且它将返回该对象:突变,但它的原型不会改变。 尽管length不是可枚举的属性,并且Object.assign不会复制它,但是第一个参数数组的行为是它将在为其分配其他属性时适应其length属性。

两者均采用浅拷贝。

结论

如果您的数组具有自定义属性,则希望复制该数组,并且该数组的末尾没有空插槽:使用Object.assign

如果您的数组没有自定义属性(或者您不关心它们)并且没有空插槽,请使用传播语法。

如果您的数组具有要复制的自定义属性,并且要保留空的插槽,则这两种方法都不会做到。 但是使用Object.assign可以更轻松地完成:

a = Object.assign([], arr, { length: arr.length });

为了简短Object.assign ,请始终使用...传播构造,切勿在数组上使用Object.assign

Object.assign用于对象。 尽管数组也是对象,但是它将对它们造成一定的影响,而这种影响几乎永远不会有用。

Object.assign(obj1, obj2)obj2所有可枚举键中获取值,并将其分配给obj1 实际上,数组是对象,而数组索引是对象键。

[...[1, 2, 3], ...[4, 5]]结果为[1, 2, 3, 4, 5]数组。

Object.assign([1, 2, 3], [4, 5])会生成[4, 5, 3]数组,因为第一个数组中01索引上的值会被第二个数组中的值覆盖。

在第一个数组为空的情况下, Object.assign([], arr)[...arr]结果相似。 但是, [...arr]的合适ES5替代方法是[].concat(arr)而不是Object.assign([], arr)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM