0

I came across this question as I was building a recursive function to drill into objects. Given an object and path (as an Array of strings):

const path = ['path', 'to', 'nestedObj', 'someProp'];

const obj = {
  path: {
    to: {
      nestedObj: {
        someProp: 'someValue'
      }
    }
  }
}

I came up with this solution:

function setValueFromPath(object, path, value) {
  let nestedObj = object[path[0]];
  const nextPath = path.slice(1, path.length);
  if(path.length > 1) {
    return setValueFromPath(nestedObj, nextPath, value);
  }
  nestedObj = value;
}

It didn't reassign the value to some prop however. To me this means the last line, in nestedObj = value, nestedObj is not holding a reference to the original obj.

So I did some fiddling and tried this:

function setValueFromPath(object, path, value) {
  let nestedObj = object[path[0]];
  const nextPath = path.slice(1, path.length);
  if(path.length > 2) {
    return setValueFromPath(nestedObj, nextPath, value);
  }
  nestedObj[path[1]] = value;
}

In this case this does mutate the original object(intended behavior). My question: Why does this nestedObj seemingly hold a reference to the original object but not the first in the first solution? I don't think it has anything to do with this being a recursive function. But I was a bit confused and was wondering if someone could shed some light.

Andrew Kim
  • 3,145
  • 4
  • 22
  • 42
  • Possible duplicate of [How to set object property (of object property of..) given its string name in JavaScript?](https://stackoverflow.com/questions/13719593/how-to-set-object-property-of-object-property-of-given-its-string-name-in-ja) – Heretic Monkey Feb 07 '18 at 16:36
  • 4
    Making `nestedObj` point to a different object has no effect on what it used to point to. – SLaks Feb 07 '18 at 16:36
  • I don't believe so, this question has more to do with references in memory – Andrew Kim Feb 07 '18 at 16:38
  • At the innermost level of recursion, you still have to `return` something. – Patrick Roberts Feb 07 '18 at 16:38
  • 1
    isn't there implicit return of undefined? I mean the function works, thats not really what my question is about either 0.0 – Andrew Kim Feb 07 '18 at 16:40
  • @Slaks doesn't `nestedObj` point to the reference in memory the property I want to change? – Andrew Kim Feb 07 '18 at 16:41
  • You actually need to set the last `property` of the object. Not the object itself – Jonas Wilms Feb 07 '18 at 16:43
  • 1
    And well the variable holds the reference. When you override a reference, you rewrite the reference, not the obkect it is pointing to. By the way: `for(const sub of path) object = object[sub];` – Jonas Wilms Feb 07 '18 at 16:44
  • that is definitely it, thank you. – Andrew Kim Feb 07 '18 at 19:48

1 Answers1

0

This is due to the fact that when you set a reference to an object, the pointer to that object is passed through, but when you set a reference to a variable, it will create a new one.

Let me explain myself, in the first iterations of you function, you will copy the object to nestedObj

let nestedObj = object[path[0]]; // so nestedObj points to path, which is an object

But in the last iteration, you will simply copy the value of someProp to nestedObj (and since it is not an object, it will create a new place in memory to stock it, and thus only change that instance of the variable).

let nestedObj = object[path[0]]; // Here nested obj is a copy of someProp
Moufett
  • 51
  • 1
  • 6