【问题标题】:Why does JavaScript property accessor allow use of arbitrarily nested array containing a single property name?为什么 JavaScript 属性访问器允许使用包含单个属性名称的任意嵌套数组?
【发布时间】:2021-10-12 20:30:23
【问题描述】:

刚刚回复了question,对于为什么以下内容似乎可以在 JavaScript 中工作感到有些困惑:

const source = {
  last: "Capulet"
};

const srcKeys = Object.keys(source);

console.log(source[srcKeys]);
console.log(source[[[[srcKeys]]]]);
console.log(source[[],[[[srcKeys]]]]);
console.log(source[[],[[srcKeys]]]);
console.log(source[[[]],[],srcKeys]);
console.log(source[[[]],[[srcKeys]]]);

为了查看兔子洞的深度,我发现以下方法不起作用:

const source = {
  last: "Capulet"
};

const srcKeys = Object.keys(source);

console.log(source[[[],[[srcKeys]]]]);
console.log(source[[[],[],[[srcKeys]]]]);
console.log(source[[[[]],[[srcKeys]]]]);

这里的逻辑是什么?

【问题讨论】:

    标签: javascript properties


    【解决方案1】:

    做了一些researchon这个问题后,原来是有办法解决这个问题的。

    Comma operator

    这在我的测试中并不是很明显,但是通过有效的示例来理解它是非常有用的。

    console.log(source[srcKeys]);
    console.log(source[[[[srcKeys]]]]);
    console.log(source[[],[[[srcKeys]]]]);
    console.log(source[[],[[srcKeys]]]);
    console.log(source[[[]],[],srcKeys]);
    console.log(source[[[]],[[srcKeys]]]);
    

    您会注意到实际上存在一种模式,这些模式最初并不明显。

    每个属性访问器要么是一个逗号表达式(它将计算表达式中的最后一个值 - 通常是一个数组),要么只是一个数组。

    console.log(source[srcKeys]); // => array
    console.log(source[[[[srcKeys]]]]); // => array
    console.log(source[[],[[[srcKeys]]]]); // => comma expression
    console.log(source[[],[[srcKeys]]]); // => comma expression
    console.log(source[[[]],[],srcKeys]); // => comma expression
    console.log(source[[[]],[[srcKeys]]]); // => comma expression
    

    更重要的是,每个数组要么是单个元素数组,要么是单个元素数组的嵌套数组

    有了这些知识,现在是尝试了解 ECMAScript 规范如何对property accessors 进行评估的好时机。

    Property Accessor

    我会省略你血淋淋的细节,而是对几乎 99% 的时间发生的事情进行总结:

    首先将属性表达式转换为字符串(除非它是自 es6 以来的 Symbol),然后返回对具有给定属性名称的值的引用


    所以现在我们了解 JavaScript 只会尝试将任何属性访问器转换为字符串,并将该字符串用作属性名称。

    除此之外,数组在转换为字符串时还有一个有趣的行为。您可以阅读其他 answer 以深入了解数组如何转换为属性名称。

    不苏秘密揭秘

    现在让我们将我们所知道的一切应用到给出的示例中,看看为什么有些有效而有些无效。

    首先,让我们看一下不起作用的例子:

    console.log(source[[[],[[srcKeys]]]]); // => property accessor expression is [[],[[srcKeys]]]
    console.log(source[[[],[],[[srcKeys]]]]); // => property accessor expression is [[],[],[[srcKeys]]]
    console.log(source[[[[]],[[srcKeys]]]]); // => property accessor expression is [[[]],[[srcKeys]]]
    

    每个表达式的一个一致细节是它们都是多个元素的数组。很快就会明白为什么这些没有给我们预期的价值,但之前的却给了我们预期的价值。为此,我现在将在所有数组上显示toString 的结果。

    const source = {
      last: "Capulet"
    };
    
    const srcKeys = Object.keys(source);
    
    // console.log(source[srcKeys]);
    console.log(srcKeys.toString());
    
    // console.log(source[[[[srcKeys]]]]);
    console.log([
      [
        [srcKeys]
      ]
    ].toString());
    
    // console.log(source[[],[[[srcKeys]]]]);
    console.log(([], [
      [
        [srcKeys]
      ]
    ]).toString());
    
    // console.log(source[[],[[srcKeys]]]);
    console.log(([], [
      [srcKeys]
    ]).toString());
    
    // console.log(source[[[]],[],srcKeys]);
    console.log(([
      []
    ], [], srcKeys).toString());
    
    // console.log(source[[[]],[[srcKeys]]]);
    console.log(([
      []
    ], [
      [srcKeys]
    ]).toString());
    
    // console.log(source[[[],[[srcKeys]]]]);
    console.log([
      [],
      [
        [srcKeys]
      ]
    ].toString());
    
    // console.log(source[[[],[],[[srcKeys]]]]);
    console.log([
      [],
      [],
      [
        [srcKeys]
      ]
    ].toString());
    
    // console.log(source[[[[]],[[srcKeys]]]]);
    console.log([
      [
        []
      ],
      [
        [srcKeys]
      ]
    ].toString());

    我们有它。第一个有效的示例都有一个 toString 值 last,而其余的都没有。

    【讨论】:

    • 起初,我认为嵌套数组的展平是一种有趣的行为。我希望数组的字符串化:[[],[[srcKeys]]] 将输出:[,[srcKeys]] 但是然后我意识到通过在每个数组元素上调用 toString 来对数组进行字符串化。
    • @Yousaf 没错。在 JS 中将数组转换为字符串产生与array.join(',') 相同的结果
    猜你喜欢
    • 2012-01-01
    • 1970-01-01
    • 2022-01-16
    • 2020-03-12
    • 1970-01-01
    • 2016-09-14
    • 2021-10-12
    • 2015-07-19
    • 2013-07-22
    相关资源
    最近更新 更多