1

Imagine this object:

var obj = {
             one: {
                two:{
                    three: "whatever"
                }
             }
          }

If I want to access "whatever" I simply do:

console.log( obj.one.two.three ) --> "whatever"

And I can even use a variable like:

var one = "one"
console.log( obj[one].two.three ) --> "whatever"

But why doesn't this work ?

var onetwo = "one.two"
console.log( obj[onetwo].three ) --> undefined
coiso
  • 7,151
  • 12
  • 44
  • 63
  • It would have to be `obj[one]["two"].three`. Notice that dots in property names are allowed, so `["one.two"]` is a single property that cannot be written in dot notation. – Bergi Oct 02 '13 at 12:05
  • yes but that would only work if I knew the exact amount of "nodes" – coiso Oct 02 '13 at 12:11
  • If you don't, you will need to use a loop over the "node" names. There is no expression for that. – Bergi Oct 02 '13 at 12:12

1 Answers1

1

But why doesn't this work ?

Because the notation is not supported in the language. It's simply not there. The specification defines property access as with bracket notation as:

MemberExpression [ Expression ]

The algorithm for defining how that works is defined in the lines below, the syntax for nested properties is simply not a part of the core language syntax.

There are specific parsers that let you do this, and you can always invoke the language compiler yourself (JS lets you do that with eval for example - don't though), but the use case is not common enough.


Note: Since you mentioned in the comments you use Angular, it already has that built in using $parse doing var res = $parse("one.two.three")(obj); Here's a fiddle.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • damn, do you know of a parser for this ? I am currently working with angular btw – coiso Oct 02 '13 at 12:04
  • @PedroEsperança: There are [many answers here on SO](http://stackoverflow.com/a/14397052/1048572) – Bergi Oct 02 '13 at 12:06
  • 1
    @PedroEsperança Angular let's you do this of course, the use case is quite common in Angular, for example in a binding with `{{obj.propertyone.propertytwo}}` this sort of parsing and scope resolution is done. Check out [`$parse`](http://docs.angularjs.org/api/ng.$parse) . It converts an Angular expression into a function. – Benjamin Gruenbaum Oct 02 '13 at 12:06
  • I'm still trying to find a way to do this with parse, could you shed any lights? – coiso Oct 02 '13 at 13:03
  • 1
    @PedroEsperança Sure, your code will probably look difference since you can just get $parse inside wherever you need it anyway instead of using the injector explicitly. In a line it's - `var res = $parse("one.two.three")(obj);` Here's a demo - http://jsfiddle.net/FNM6v/ – Benjamin Gruenbaum Oct 02 '13 at 14:07
  • worked like a charm :) the problem now is that I am not being able to change the values on the service :p I am using this like: $parse("path to item")(injectedservice) It gives me a ReferenceError: Invalid left-hand side in assignment :s – coiso Oct 02 '13 at 16:19
  • 1
    @PedroEsperança that sounds like a new question to me. I don't want to go on and discuss a new topic on the same question. Please consider opening a new question about that if it's not clear to you. (Include a fiddle while you're at it - ReferenceError seems unlikely if that's all there is to it). Note that the syntax for changing and the syntax for retrieving in $parse is different (with .assign - see the docs). – Benjamin Gruenbaum Oct 02 '13 at 16:26
  • thank you so much @BenjaminGruenbaum can I ask what you are working on ? add me anywhere: buesimples@gmail.com – coiso Oct 02 '13 at 17:01
  • @PedroEsperança Several things, I would not publish my email here if I were you. SO is a public site. Anyway, discussion in comments is frowned upon in Stack Overflow. I'm often in [the JavaScript chatroom](http://chat.stackoverflow.com/rooms/17/javascript) , you're welcome to find me there :) – Benjamin Gruenbaum Oct 02 '13 at 17:10