2

Lets say I have an object generated from an xml document it is very deep, so I can reach a value like:

myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.value

If I want to update this property based on it's previous value then I could do it like this:

myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.value = 
updateFn(
  myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.value,
  otherparam1, otherparam2);

This makes my code very hard to read, is there any nice solution to pass a parameter as a reference not by value?

So then my code could look like this:

updateFn(ref, param1, param2) {
  // "ref =" act as a reference, "(ref)" act as a value
  ref = someThingToDoWithTheOldValue(ref);
}

Call it like this:

updateFn(
  myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.value,
  otherparam1, otherparam2);
// So I can omit the myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.value =  part
micnic
  • 10,915
  • 5
  • 44
  • 55
NoNameProvided
  • 8,608
  • 9
  • 40
  • 68
  • 4
    `var o = myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$` then `o.value = whatever`. – RobG Jun 29 '15 at 11:11
  • if I do that, then I only have the `$` object in the 'o' variable, but I need the whole stuff later. – NoNameProvided Jun 29 '15 at 11:15
  • 1
    And you'd still have "the whole stuff" later accessible via the full chain of properties from `myobject`, in addition to having the `o` variable that is a direct reference to the `...$` object. – nnnnnn Jun 29 '15 at 11:19
  • 1
    Related: [Is JavaScript a pass-by-reference or pass-by-value language?](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language) – laggingreflex Jun 29 '15 at 11:29

2 Answers2

4

You can assign a variable name to any deep down properties.

var desired_$ = myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$

Any changes made to desired_$ will actually reflect on myobject.really...desired.$

desired_$.value = updateFn( desired_$.value, otherparam1, otherparam2);

You can pass myobject around and myobject.really...desired.$.value would still be what you set through desired_$.value above.


Does this mean if I pass the 'myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$' as a paramter in the function, then it will reflect the canges on the original object too?

It depends on what you actually do with it. Here' the general rule: If you change a property on an object, the object stays the same - i.e. you can pass that object and its property that you changed will hold the value that you changed it to.

For example:

var obj = { outer: { inner: {prop: 1} } };

I have two function that change the properties in following ways:

function changeProp(prop){
    prop = 2;
}
function changeInner(inner){
    inner.prop = 2;
}

Then their respective effects would be as such:

changeProp(obj.outer.inner.prop);
obj.outer.inner.prop //=> 1   // original unchanged

changeInner(obj.outer.inner);
obj.outer.inner.prop //=> 2   // original changed!

So as long as you change the child property on an object, the original object reflects the changes.

laggingreflex
  • 32,948
  • 35
  • 141
  • 196
  • Does this mean if I pass the `myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$` as a paramter in the function, then it will reflect the canges on the original object too? – NoNameProvided Jun 29 '15 at 11:29
  • ``changeProp`` and ``changeInnerCompletely`` should work the same. The last call does not change inner. – Sam Thomas Jan 04 '23 at 00:10
  • 1
    @SamThomas Good catch! I don't even remember what I was thinking there... Edited. – laggingreflex Jan 04 '23 at 11:03
  • @laggingreflex I was actually looking for a way to achieve it :D , something that will be interesting for beginners is that in your second function you can do as many inner.something assigns and it will get reflected back to the original object. But as soon as you assign inner itself to something else, the underlying lvalue for inner changes and you have lost the reference. Any following inner.something assignments won't reflect back. – Sam Thomas Jan 04 '23 at 18:51
0

you could do something like

    function setProp(ref, prop, val)
    {
           ref[prop] = val;
    }

    ...
      setProp(myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$, "value", "new Value");

but I doubt that this makes your code more readable anyhow ...

IDEA

add a generic setter to each object:

    Object.prototype.setProp = function(prop, val)
    {
           this[prop] = val;
    }

and then:

myobject.really[0].long.chain[43].to.travel.to.get.my[5].desired.$.setProp("value", "new Value");

small fiddle here

Axel Amthor
  • 10,980
  • 1
  • 25
  • 44