Why does javascript evaluate the following as true, given that object foo
has a valid property bar
?
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"]
?
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:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
What aspect of the language or parser is causing this behavior? Thanks!
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"
.
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"]]
.
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"]
is also an array with one element, which is a string, so the string representation of ["bar"]
is just "bar"
.
What this comes down to is: [[["bar"]]].toString() === "bar"
and foo[[[["bar"]]]]
is the same as foo[[[["bar"]]].toString()]
.
You would also find that:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2"
.
Let's see how foo[[[["bar"]]]]
is evaluated, step-by step:
The outermost brackets in foo[...]
denote a property
accessor. The expression foo[[[["bar"]]]]
thus translates to
accessing a property of foo
with name [[["bar"]]]
.
According to the ECMA standard, the abstract operation
ToPropertyKey(name) is then used to turn the name [[["bar"]]]
into a property key value:
A property key value is either an ECMAScript String value or a Symbol value.
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"]]].toString() === "bar"
Which finally means that our property key actually becomes "bar"
:
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With