我在这里有一些代码,我想知道它是相同的还是不同的。我很确定这些都是相同的,但我不确定我是否做得对。
let zoneComment = updatedMap[action.comment.zone]
? [...updatedMap[action.comment.zone]] : [];
let zoneComment = updatedMap[action.comment.zone]
? Object.assign([], updatedMap[action.comment.zone]) : [];
如果这些是相同的,那么我应该使用它还是重要的?我想使用最佳实践,如果你的观点更好,那么请说明。
答案 0 :(得分:3)
在您的特定情况下,他们不相同。
原因是你有一个数组,而不是一个对象。
在数组上执行...
将展开数组中的所有元素(但不是属性)
执行Object.assign
期望一个对象,所以它会将一个数组视为一个对象并将所有enumerable自己的属性复制到其中,而不仅仅是元素:
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这样的工具进行预处理步骤(转换)。
答案 1 :(得分:1)
你的问题确实起泡到了:
当[...arr]
是数组时,Object.assign([], arr)
和arr
是否会提供相同的结果?
答案是:通常,是的,但是:
如果arr
是一个稀疏数组,其最后一个插槽没有值,则结果的length
属性在两种情况下都不相同:扩展语法将保持不变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
执行此操作,因为它的第一个参数是一个数组,它将返回的对象:mutated,但它的proto不会改变。虽然length
不是可枚举属性,Object.assign
不会复制它,但第一个参数数组的行为是它将调整其length
属性,因为其他属性已分配给它。
两者都是浅色副本。
如果您的数组具有您想要复制的自定义属性,并且最后没有空插槽:请使用Object.assign
。
如果您的数组没有自定义属性(或者您不关心它们)并且没有空插槽:请使用扩展语法。
如果您的阵列具有您想要复制的自定义属性,并且想要维护空插槽:两种方法都不会同时执行这两项操作。但是使用Object.assign
更容易实现:
a = Object.assign([], arr, { length: arr.length });
答案 2 :(得分:1)
要简短,请始终使用...
点差构造,而不要在数组上使用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]
数组,因为第一个数组中的0
和1
索引上的值会被第二个数组中的值覆盖。
如果第一个数组为空,Object.assign([], arr)
和[...arr]
结果相似。但是,[...arr]
的正确ES5替代方法是[].concat(arr)
,而不是Object.assign([], arr)
。