object[[["key"]]] 如何计算为 javascript 中的 object["key"]?

How does object[[["key"]]] evaluate to object["key"] in javascript?

鉴于对象 foo 具有有效的 属性 bar,为什么 javascript 评估以下为真?

foo[[[["bar"]]]] === foo["bar"]

根据运算符的优先级,我认为 foo[[[["bar"]]]] 正在尝试以数组 [[["bar"]]] 作为键来访问 属性,但为什么仍然 "flatten down"与 foo["bar"]?

相同

我的同事说 javascript 解析器有括号简化功能,忽略了额外的括号。我不认为这是真的,因为将 [[["foo"]]] 保存到变量 test 会得到相同的结果:

> test = [[["bar"]]]
 [Array[1]]
> foo["bar"] = 5
 5
> foo[test]
 5

语言或解析器的哪个方面导致了这种行为?谢谢!

让我们逐步了解如何评估 foo[[[["bar"]]]]

  1. foo[...]中最外面的括号表示a 属性 存取器。因此,表达式 foo[[[["bar"]]]] 转换为 访问名称为 [[["bar"]]]foo 的 属性。

  2. 根据ECMA standard,进行抽象操作 ToPropertyKey(name)然后用来转名字[[["bar"]]] 进入 属性 键值:

    A property key value is either an ECMAScript String value or a Symbol value.

    名称[[["bar"]]]不是Symbol类型,因此被转换 成一个字符串。通过 连接数组的所有内容将数组转换为字符串 字符串转换值:

    [[["bar"]]].toString() === "bar"
    
  3. 这最终意味着我们的 属性 键实际上变成了 "bar":

    foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
    

JavaScript 括号表示法接受表达式,但它总是将该表达式的值转换为字符串。因此,如果您传入一个数组,它会尝试将其转换为字符串。在您的情况下,您传递的是数组 [[["bar"]]][[["bar"]]].toString() === "bar".

如果您想知道为什么 [[["bar"]]].toString() === "bar",那是因为当数组 arr 隐式转换为字符串时,就像调用 arr.join(',') 一样。也就是说,它的每个元素都被转换为字符串,然后以逗号分隔的字符串连接起来。当数组只有一个元素时,数组的字符串表示就是该元素的字符串表示。在您的例子中,您的数组 ([[["bar"]]]) 有一个元素:[["bar"]]

该数组也转换为字符串,并且由于它也是一个元素数组,因此它的字符串表示形式是该单个元素的字符串表示形式:["bar"].

["bar"]也是一个数组,只有一个元素,是一个字符串,所以["bar"]的字符串表示就是"bar".

归结为:[[["bar"]]].toString() === "bar"

foo[[[["bar"]]]]等同于foo[[[["bar"]]].toString()]

您还会发现:

foo[[[[1]],[2]]] === foo["1,2"]

因为:[[[1]],[2]].toString() === "1,2".