【问题标题】: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 是否要求不使用函数调用或循环?

标签: javascript destructuring


【解决方案1】:

此时您可以同时使用For of loopES6 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 循环不同
      猜你喜欢
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 2020-11-07
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多