为所有元素解构数组内的对象属性

Posted

技术标签:

【中文标题】为所有元素解构数组内的对象属性【英文标题】:Destructure object properties inside array for all elements 【发布时间】:2017-02-25 10:17:23 【问题描述】:

在其最基本的形式中,有一个对象数组:

let arr = [
  val:"a",
  val:"b"
];

如何使用解构,只获取值['a', 'b']

获取第一个值很容易:

let [val:res] = arr; //res contains 'a'

可以通过rest操作符来获取数组中的所有值:

let [...res] = arr; //res contains all objects

结合这些,我希望能够使用:

let [...val:res] = arr; //undefined, expected all 'val's (['a', 'b'])

以上返回未定义(在 FF 中测试)。一些进一步的测试似乎表明,在使用对象解构时添加 rest 运算符也不会使用迭代,而是取回原始对象,例如let [...length:res] = arr; //res= 2。其他一些试验,例如let [val:...res] = arr;let [val:...res] = arr; 会产生语法错误。

使用其他方法很容易,例如在数组上使用map,但大多数情况下,我在解构多个级别(具有包含数组的对象的数组)时偶然发现了这个问题。因此,我真的在尝试解决如何仅通过解构来做到这一点。 为方便起见:a test fiddle

编辑

如果我未能解释问题的目标,我深表歉意。我不是在寻找特定问题的解决方案,只是为了找到解构时使用的正确语法。

否则,第一个问题将是:在上面的示例中,为什么let [...val:res] = arr; 不返回所有值(['a', 'b'])。第二个问题是:在嵌套对象解构中使用 rest 运算符的正确语法是什么? (很确定我在这里混淆了一些定义)。似乎不支持后者,但我没有遇到任何不支持(以及为什么)不支持的文档。

【问题讨论】:

你希望res 在这样的解构过程中变成什么?什么是“所有 vals”? @Bergi 我原以为它会返回['a', 'b'](它是let [val:res] = arr;let [...res] = arr; 的组合) @Me.Name "第二个问题是:在嵌套对象解构中使用 rest 运算符的正确语法是什么?(很确定我在这里混淆了一些定义)。” 见What is SpreadElement in ECMAScript documentation? Is it the same as Spread operator at MDN? @Me.Name 是否要求不使用函数调用或循环? 【参考方案1】:

此时您可以同时使用For of loop 和ES6 Object destructuring。

let arr = [val:"a",val:"b"];
    
    
    for (const item in arr)
        const val = arr[item];
        console.log(val);
    

【讨论】:

【参考方案2】:

可以在解构赋值之前声明赋值目标;在解构目标处,通过从解构源设置赋值目标索引的值

let arr1 = [val: "a", val: "b"];

let arr2 = ["foo":1,"arr":["val":"a","val":"b"]
           , "foo":2,"arr":["val":"c","val":"d"]];

let [res1, res2] = [[], []];

[val: res1[0], val: res1[1]] = arr1;

[arr: [val:res2[0], val:res2[1]]
, arr: [val:res2[2], val:res2[3]]] = arr2;

console.log(res1, res2);

您也可以在目标中使用rest element 在源中收集值,方法是按照对象模式包含comma 运算符以返回从对象中提取的值

let arr = [val: "a", val: "b"];

let [...res] = [(val = arr[0], val), (val = arr[1], val)];

console.log(res)

【讨论】:

【参考方案3】:

为什么let [...val:res] = arr; 不返回所有值 (['a', 'b'])?

您似乎将其余语法与数组推导混淆了。

如果您为[someElements, ...someExpression] 分配一个值,该值将被测试为可迭代,然后将迭代器生成的每个元素分配给相应的someElements 变量。如果在解构表达式中使用 rest 语法,则会创建一个数组并运行迭代器直到其结束,同时用生成的值填充数组。然后将该数组分配给someExpression

所有这些赋值目标都可以是其他解构表达式(任意嵌套和递归计算),或者对变量或属性的引用。

因此,如果您执行let [...val:res] = arr,它将创建一个数组并用来自arr 的迭代器的所有值填充:

let val:res = Array.from(arr[Symbol.iterator]())

您现在可以看到为什么以undefined 结尾,以及为什么使用[...length:res] 之类的东西确实会产生结果。另一个例子:

let [val:res1, ...length: res2] = arr;
console.log(res1) // 'a'
console.log(res2) // 1 (length of `[val: 'b']`)

如何使用解构来仅获取值['a', 'b']

一点也不。使用map 方法。

【讨论】:

@guest271314 为什么?如果您参考您的帖子,这与我的回答有什么关系? "可以使用解构来仅获取值['a', 'b']?"。您答案的“根本不是”部分。可以通过为从= 右侧的输入数组中检索到的每个预期值声明一个唯一变量,然后将定义的变量推送到数组中。尝试使用spread 元素在使用[prop]: [...res] 的解构赋值中扩展数组,但尚未找到在下一个赋值索引处将"a" 扩展为res 的方法 @guest271314 如果声明多个变量,则它不适用于任意长度的数组。如果你使用循环,那么就不再是解构了。 没有考虑任意长度的数组,因为 OP 的数组只包含四个元素。对于任意长度的数组,这里的第一印象是尝试将变量分配为对象的属性,而不是例如a;不确定这是否可能。会尝试这种方法。此处发表评论的原因是由于您的答案的“根本没有”部分。如果您对答案的那部分没问题,我也在这里。还发表了评论,因为您可能会注意到答案的该部分可能有所改进 看看你的意思...【参考方案4】:

除了映射与值的回调

let arr = [ val: "a" ,  val: "b" ];

console.log(arr.map(o => o.val));

您可以在参数列表中使用解构并仅使用返回的值。

let arr = [ val: "a" ,  val: "b" ];

console.log(arr.map((val) => val));

【讨论】:

嗨,尼娜。谢谢你回复我的帖子。我一直很喜欢你的帖子和你提供的简洁答案:) 但是在这种情况下,它不是关于特定场景,而是为了找到一个通用的语法解决方案。我认为有一种语法可以对未知数量的元素进行解构,因此可以在 [foo:1, arr:[ val:"a", val:"b"],foo:2, arr:[ val:"c", val:"d"] ] 上使用相同的语法 我的误解是你想要达到的结果。我(非常)依赖示例,对我来说,不清楚你想要实现什么。我看不到对象是源对象还是目标对象。如果您包括源和目标,也许 itz 会更清楚。 我们的目标是找出如何(以及是否)可以使用解构来获取多个值,例如这样。既然存在rest 运算符(let [...res] = arr; 有效)并且允许嵌套属性,为什么let [...val:res] = arr; 不给出所有值。我以为这是我的某种疏忽,但我开始担心这是不可能的。不是具体的问题或例子,所以恐怕不能给出具体的来源和目标,只能举例。【参考方案5】:

你可以像这样解构嵌套对象

https://developer.mozilla.org/en/docs/Web/javascript/Reference/Operators/Destructuring_assignment#Nested_object_and_array_destructuring

let arr = [
  val:"a",
  val:"b"
];

const [val: valueOfA, val: valueOfB] = arr

console.log(
  valueOfA, valueOfB
)

【讨论】:

感谢您的回答。我知道map可以使用,我也可以使用for(val:v of arr) console.log(v);来组合解构和循环,甚至在map中使用解构,但是如果rest运算符可以用于对象本身并且解构可以用于嵌套属性,为什么不能在对象解构上使用rest运算符?我找不到关于它的支持的文档,但也没有关于它不受支持的文档。 其实我完全不正确。您可以解构嵌套对象 一次每个元素确实是可能的,但是对于未知数量的条目,您将如何做呢? (不包括for..of @Me.Name "(not count for..of )" 为什么不能使用for..of?要求是什么? for...of 是一个迭代器循环,每次迭代都会声明变量,与for...infor 循环不同

以上是关于为所有元素解构数组内的对象属性的主要内容,如果未能解决你的问题,请参考以下文章

将数组解构为对象属性键

JS对象解构

Es6 -- 对象的解构赋值

对象的解构赋值

1.3 解构赋值变量赋值

ES6解构赋值 (数组 , 对象)