This question already has an answer here:
这个问题在这里已有答案:
- Why does accessing an element in an object using an array as a key work? 3 answers
- 为什么使用数组作为关键工作来访问对象中的元素? 3个答案
Why does javascript evaluate the following as true, given that object foo
has a valid property bar
?
为什么javascript会将以下内容评估为true,因为对象foo具有有效的属性栏?
foo[[[["bar"]]]] === foo["bar"]
Based on operator precedence, I would think foo[[[["bar"]]]]
is trying to access a property with the array [[["bar"]]]
as the key, but why does that still "flatten down" to the same as foo["bar"]
?
基于运算符优先级,我认为foo [[[[“bar”]]]]试图以数组[[[“bar”]]]作为键来访问属性,但为什么它仍然“平坦化” “就像foo [”bar“]一样?
Colleagues of mine are saying javascript parsers have bracket simplifying which ignores the extra brackets. I don't think this is true since saving [[["foo"]]]
to a variable test
gives the same result:
我的同事们说javascript解析器有简化括号,忽略了额外的括号。我不认为这是真的,因为将[[[“foo”]]]保存到变量测试会得到相同的结果:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
What aspect of the language or parser is causing this behavior? Thanks!
语言或解析器的哪个方面导致了这种行为?谢谢!
2 个解决方案
#1
7
JavaScript bracket notation accepts an expression, but it always converts the value of that expression to a string. Thus if you pass in an array, it will attempt to convert it to a string. In your case you are passing in an array [[["bar"]]]
, and [[["bar"]]].toString() === "bar"
.
JavaScript括号表示法接受表达式,但它始终将该表达式的值转换为字符串。因此,如果传入数组,它将尝试将其转换为字符串。在你的情况下,你传入一个数组[[[“bar”]]]和[[[“bar”]]]。toString()===“bar”。
If you are wondering why [[["bar"]]].toString() === "bar"
, it is because when an array arr
is converted to a string implicitly it is like calling arr.join(',')
. That is each of its elements are converted to strings and then joined in a comma separated string. When the array only has one element, the string representation of the array is just the string representation of that one element. In your case your array ([[["bar"]]]
) has one element: [["bar"]]
.
如果你想知道为什么[[[“bar”]]]。toString()===“bar”,那是因为当数组arr被隐式转换为字符串时,就像调用arr.join(',') 。也就是说,它的每个元素都被转换为字符串,然后以逗号分隔的字符串连接。当数组只有一个元素时,数组的字符串表示只是该元素的字符串表示。在您的情况下,您的数组([[[“bar”]]])有一个元素:[[“bar”]]。
That array is converted to a string too, and since it is also a one element array, the string representation of it is the string representation of that single element: ["bar"]
.
该数组也被转换为字符串,因为它也是一个单元素数组,它的字符串表示形式是该单个元素的字符串表示形式:[“bar”]。
["bar"]
is also an array with one element, which is a string, so the string representation of ["bar"]
is just "bar"
.
[“bar”]也是一个带有一个元素的数组,它是一个字符串,因此[“bar”]的字符串表示只是“bar”。
What this comes down to is: [[["bar"]]].toString() === "bar"
这归结为:[[[“bar”]]]。toString()===“bar”
and foo[[[["bar"]]]]
is the same as foo[[[["bar"]]].toString()]
.
和foo [[[[“bar”]]]]与foo [[[[“bar”]]]。toString()]相同。
You would also find that:
您还会发现:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2"
.
因为:[[[1]],[2]]。toString()===“1,2”。
#2
6
Let's see how foo[[[["bar"]]]]
is evaluated, step-by step:
让我们看看如何评估foo [[[[“bar”]]]]的步骤:
-
The outermost brackets in
foo[...]
denote a property accessor. The expressionfoo[[[["bar"]]]]
thus translates to accessing a property offoo
with name[[["bar"]]]
.foo [...]中最外面的括号表示属性访问器。表达式foo [[[[“bar”]]]]因此转换为访问名为[[[“bar”]]]的foo属性。
-
According to the ECMA standard, the abstract operation ToPropertyKey(name) is then used to turn the name
[[["bar"]]]
into a property key value:根据ECMA标准,抽象操作ToPropertyKey(name)然后用于将名称[[[“bar”]]]转换为属性键值:
A property key value is either an ECMAScript String value or a Symbol value.
属性键值是ECMAScript字符串值或符号值。
The name
[[["bar"]]]
is not of type Symbol and thus converted into a string. An array is converted to a string by joining all its string converted values:名称[[[“bar”]]]不是Symbol类型,因此转换为字符串。通过连接其所有字符串转换值,将数组转换为字符串:
[[["bar"]]].toString() === "bar"
-
Which finally means that our property key actually becomes
"bar"
:这最终意味着我们的属性键实际上变成了“bar”:
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
#1
7
JavaScript bracket notation accepts an expression, but it always converts the value of that expression to a string. Thus if you pass in an array, it will attempt to convert it to a string. In your case you are passing in an array [[["bar"]]]
, and [[["bar"]]].toString() === "bar"
.
JavaScript括号表示法接受表达式,但它始终将该表达式的值转换为字符串。因此,如果传入数组,它将尝试将其转换为字符串。在你的情况下,你传入一个数组[[[“bar”]]]和[[[“bar”]]]。toString()===“bar”。
If you are wondering why [[["bar"]]].toString() === "bar"
, it is because when an array arr
is converted to a string implicitly it is like calling arr.join(',')
. That is each of its elements are converted to strings and then joined in a comma separated string. When the array only has one element, the string representation of the array is just the string representation of that one element. In your case your array ([[["bar"]]]
) has one element: [["bar"]]
.
如果你想知道为什么[[[“bar”]]]。toString()===“bar”,那是因为当数组arr被隐式转换为字符串时,就像调用arr.join(',') 。也就是说,它的每个元素都被转换为字符串,然后以逗号分隔的字符串连接。当数组只有一个元素时,数组的字符串表示只是该元素的字符串表示。在您的情况下,您的数组([[[“bar”]]])有一个元素:[[“bar”]]。
That array is converted to a string too, and since it is also a one element array, the string representation of it is the string representation of that single element: ["bar"]
.
该数组也被转换为字符串,因为它也是一个单元素数组,它的字符串表示形式是该单个元素的字符串表示形式:[“bar”]。
["bar"]
is also an array with one element, which is a string, so the string representation of ["bar"]
is just "bar"
.
[“bar”]也是一个带有一个元素的数组,它是一个字符串,因此[“bar”]的字符串表示只是“bar”。
What this comes down to is: [[["bar"]]].toString() === "bar"
这归结为:[[[“bar”]]]。toString()===“bar”
and foo[[[["bar"]]]]
is the same as foo[[[["bar"]]].toString()]
.
和foo [[[[“bar”]]]]与foo [[[[“bar”]]]。toString()]相同。
You would also find that:
您还会发现:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2"
.
因为:[[[1]],[2]]。toString()===“1,2”。
#2
6
Let's see how foo[[[["bar"]]]]
is evaluated, step-by step:
让我们看看如何评估foo [[[[“bar”]]]]的步骤:
-
The outermost brackets in
foo[...]
denote a property accessor. The expressionfoo[[[["bar"]]]]
thus translates to accessing a property offoo
with name[[["bar"]]]
.foo [...]中最外面的括号表示属性访问器。表达式foo [[[[“bar”]]]]因此转换为访问名为[[[“bar”]]]的foo属性。
-
According to the ECMA standard, the abstract operation ToPropertyKey(name) is then used to turn the name
[[["bar"]]]
into a property key value:根据ECMA标准,抽象操作ToPropertyKey(name)然后用于将名称[[[“bar”]]]转换为属性键值:
A property key value is either an ECMAScript String value or a Symbol value.
属性键值是ECMAScript字符串值或符号值。
The name
[[["bar"]]]
is not of type Symbol and thus converted into a string. An array is converted to a string by joining all its string converted values:名称[[[“bar”]]]不是Symbol类型,因此转换为字符串。通过连接其所有字符串转换值,将数组转换为字符串:
[[["bar"]]].toString() === "bar"
-
Which finally means that our property key actually becomes
"bar"
:这最终意味着我们的属性键实际上变成了“bar”:
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]