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)
语言或解析器的哪个方面导致了这种行为?谢谢!
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".
让我们看看如何foo[[[["bar"]]]]评估,一步一步:
最外面的括号foo[...]表示属性访问器.因此,表达式foo[[[["bar"]]]]转换为访问foo具有名称的属性[[["bar"]]].
根据ECMA标准,抽象操作
ToPropertyKey(name)然后用于将名称[[["bar"]]]
转换为属性键值:
甲属性密钥值或者是一个ECMAScript的字符串值或符号值.
该名称[[["bar"]]]不是Symbol类型,因此转换为字符串.通过连接其所有字符串转换值,将数组转换为字符串:
[[["bar"]]].toString() === "bar"
Run Code Online (Sandbox Code Playgroud)这最终意味着我们的属性键实际上变为"bar":
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
Run Code Online (Sandbox Code Playgroud)