对象[[["key"]]]如何在javascript中评估对象["key"]?

Mik*_*ike 7 javascript arrays accessor

为什么javascript会将以下内容评估为true,因为该对象foo具有有效属性bar

foo[[[["bar"]]]] === foo["bar"]
Run Code Online (Sandbox Code Playgroud)

基于运算符优先级,我认为foo[[[["bar"]]]]是尝试以数组[[["bar"]]]作为键访问属性,但为什么它仍然"平坦化"到相同的foo["bar"]

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

> test = [[["bar"]]]
 [Array[1]]
> foo["bar"] = 5
 5
> foo[test]
 5
Run Code Online (Sandbox Code Playgroud)

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

Pau*_*aul 7

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

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

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

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

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

foo[[[["bar"]]]]是一样的foo[[[["bar"]]].toString()].

您还会发现:

foo[[[[1]],[2]]] === foo["1,2"]
Run Code Online (Sandbox Code Playgroud)

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


le_*_*e_m 6

让我们看看如何foo[[[["bar"]]]]评估,一步一步:

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

  2. 根据ECMA标准,抽象操作 ToPropertyKey(name)然后用于将名称[[["bar"]]] 转换为属性键值:

    属性密钥值或者是一个ECMAScript的字符串值或符号值.

    该名称[[["bar"]]]不是Symbol类型,因此转换为字符串.通过连接其所有字符串转换值,将数组转换为字符串:

    [[["bar"]]].toString() === "bar"
    
    Run Code Online (Sandbox Code Playgroud)
  3. 这最终意味着我们的属性键实际上变为"bar":

    foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
    
    Run Code Online (Sandbox Code Playgroud)