Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 275
Mike Avatar asked Jun 10 '16 22:06

Mike


2 Answers

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".

like image 83
Paul Avatar answered Oct 20 '22 19:10

Paul


Let's see how foo[[[["bar"]]]] is evaluated, step-by step:

  1. The outermost brackets in foo[...] denote a property accessor. The expression foo[[[["bar"]]]] thus translates to accessing a property of foo with name [[["bar"]]].

  2. 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"
    
  3. Which finally means that our property key actually becomes "bar":

    foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
    
like image 33
le_m Avatar answered Oct 20 '22 18:10

le_m