扩展语法无法按预期与对象数组一起工作
Posted
技术标签:
【中文标题】扩展语法无法按预期与对象数组一起工作【英文标题】:Spread syntax not working as expected with array of objects 【发布时间】:2017-10-12 21:54:31 【问题描述】:我有一个反应组件,我试图将对象传播到构造函数中的状态中。
constructor()
super()
const shapesArray = [1, 2, 3]
let renderStates = shapesArray.map((el, i) =>
return ['shape'+i]: 'black'
)
this.state = ...renderStates
console.log(this.state)
我想通过this.state.shape0
访问颜色,
但是当我控制台日志this.state
时,我得到了这个:
而不是Object shape0: "black", shape1: "black", shape2: "black"
。
我在这里做错了什么?
【问题讨论】:
你没有在数组文字中使用扩展语法???那应该是 ES6 中的语法错误(也许你启用了一些实验性的 babel 东西) 顺便说一句,对于形状集合等索引值,您应该始终使用对象。 您的renderStates
是一个数组。你不应该使用[...renderStates]
吗?
...
is not an operator!
【参考方案1】:
那是因为你将一个数组传播到一个对象中。数组实际上是(通常)以连续整数 strings 作为键的对象。这些键是数组的索引。
如下图,map
接受一个数组并产生另一个数组
const shapesArray = [1, 2, 3];
const renderStates = shapesArray.map((el, i) =>
return
['shape' + i]: 'black'
);
console.log(renderStates);
当传播到一个对象中时,源对象中每个自己的可枚举属性的值被添加到其各自键下的目标中。由于数组的键是它的索引,因此您最终会得到一个对象,该对象具有数组的每个元素的属性。每个属性的名称是它在数组中的索引。
要实现您想要的,您可以使用Array.prototype.reduce
从数组中构建一个对象,并使用在映射过程中创建的名称。
const shapesArray = [1, 2, 3];
const renderStates = shapesArray
.map((el, i) =>
return
['shape' + i]: 'black'
)
.reduce((o, element) =>
Object.keys(element).forEach(key => o[key] = element[key]);
return o;
, );
console.log(renderStates);
当然,这本身可以通过在reduce内部传播对象来更优雅地编写。
const shapesArray = [1, 2, 3];
const renderStates = shapesArray
.map((el, i) =>
return
['shape' + i]: 'black'
)
.reduce((o, element) => (...o, ...element), );
console.log(renderStates);
【讨论】:
使用Object.assign
而不是 forEach
循环或非标准语法
完美,谢谢!我在想你可以将renderStates
数组(对象)的值传播到一个对象中,它们的键就是索引。【参考方案2】:
作为对aluan-haddad's answer的优化,reduce可以处理map中的逻辑
const shapesArray = [1, 2, 3];
const renderStates = shapesArray
.reduce((acc, _, i) => (
...acc,
['shape' + i]: 'black',
), );
console.log(renderStates);
【讨论】:
很好,但是你需要指定3个参数,因为第3个绑定到索引,第二个绑定到元素,第一个绑定到累加器。请注意,乍一看,这看起来是正确的,因为数组包含连续数字,但实际上相差 1。 感谢@AluanHaddad。【参考方案3】:renderStates
是一个数组,它具有从 0 开始的整数属性 或数组索引(如果您想具体说明),因此...renderStates
将获取每个索引,并从该索引创建映射到与该索引对应的值,要实现您要查找的内容,您需要将 renderStates
数组减少为这样的对象
let renderStates = shapesArray.map((el, i) =>
return ['shape'+i]: 'black'
).reduce((resultObj, currentShape,index) => resultObj['shape'+index] = currentShape['shape'+index]), );
renderStates
现在是一个对象,你可以传播它,它会产生你想要的结果
【讨论】:
【参考方案4】:无需对数组进行两次迭代。使用减少:
const shapesArray = [1, 2, 3];
const renderStates = shapesArray.reduce((accumulator, i) =>
accumulator['shape' + i] = 'black';
return accumulator;
, );
console.log(renderStates);
【讨论】:
以上是关于扩展语法无法按预期与对象数组一起工作的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中对整数数组进行线性搜索时,SSE 比较无法按预期工作