Jump to content

Is there another way to access nested Object properties?


rich
 Share

Recommended Posts

This one is bugging me, but basically.. I want to have a function that takes a key and a new value and set that across multiple objects. I'm using this approach:

child[key] = value;

Which works great if you do:

update('y', 100);

Because the child object has a y property.

 

However what I need to support is this too:

update('body.velocity.y', 100);

Now the 'body.velocity' object exists as a property of child, but of course using a string like this breaks the child[key] approach, as it's looking for a property actually named 'body.velocity.y'.

 

Is there another way of doing this? (it has to be FAST, this is for an internal loop, so I don't want to have to be splitting strings and the likes if I can help it).

Link to comment
Share on other sites

I think this is a great opportunity for a recursive function:

function update(object, key, value){	var nestedarr = String.split(key, ".");	nestedUpdate(object, nestedarr, value);}function nestedUpdate(object, nestedarr, value){	if(nestedarr.length > 1){		nestedUpdate(object[nestedarr[0]], nestedarr.shift()) //Pop first element off array	}else{		object[nestedarr[0]] = value;	}}

Note that this specific example is untested, the naming is horrible and might have bugs, but you get the general idea.

Link to comment
Share on other sites

Well, splitting the string on its dots and then Hangling through the objects should work and is imho the cleanest approach.

About the performance, what about this:

Create a hashtable that uses the whole string as key and stores references to the object it points to.

So you dont have to split the string all the times and hangle trough all objects but can grab your target directly from the cache to read/write on it.

Link to comment
Share on other sites

I've done this quite a bit in different places, this is what I normally use:

//the object to manipulatevar obj = {    some: {        deep: {            prop: 1        }    }};    //get the levels to walkvar levels = 'some.deep.prop'.split('.'),    // leave the last element    i = levels.length-1,    //the object to use to walk    o = obj;//walk to the level just before our propertywhile(i--){    o = o[levels.shift()];}//use the last key in the array to set the propertyo[levels.shift()] = 'foobar';
Your case would be something like:

 

MyObject.prototype.update = function(key, value) {    //get the levels to walk    var levels = key.split('.'),        // leave the last element        i = levels.length-1,        //the object to use to walk        o = this;    //walk to the level just before our property    while(i--){        o = o[levels.shift()];    }    //use the last key in the array to set the property    o[levels.shift()] = value;}
 

Should work fine for cases like

 

update('body.velocity.y', 10);
and

update('id', 10);
 

Hope this helps!

Link to comment
Share on other sites

I think this one performs faster:

MyObject.prototype.update = (function() {  var cache = {}, props, i, n, o;  return function(key, value, deep) {    o = this;    if (deep) {      if (!(props = cache[key])) {        cache[key] = props = key.split('.');      }      for (i = 0, n = props.length - 1; i < n; i++) {        o = o[props[i]];      }      o[props[n]] = value;    } else {      o[key] = value;    }  };})();
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...