Replace nested property for an interview During an interview I was given this interesting JavaScript task:

Given the code:
const testStr = &quot;bar.baz.foo:111222&quot;,
      testObj = {
        bar: {
          baz: {
            foo: 333444,
            foo2: 674654
          },
          boo: {
            faa: 11
          }
        },
        fee: 333
      };

function replaceInObj(obj, str) {
  // your code
}

write the implementation of the replaceInObj function

I was not allowed to use a 3rd-party library. I kinda solved the task, but I'm not satisfied with my solution and I'm struggling with my complex implementation. At the same time I cannot find another solution by myself.
My implementation of the replaceInObj function


const testStr = 'bar.baz.foo:111222';
const testObj = {
  bar: {
    baz: {
      foo: 333444,
      foo2: 674654,
    },
    boo: {
      faa: 11,
    },
  },
  fee: 333,
};

console.log('[before] testObj.bar.baz =', testObj.bar.baz);

// run
replaceInObj(testObj, testStr);

console.log('[after] testObj.bar.baz =', testObj.bar.baz);

function replaceInObj(obj, str) {
  const [path, valueToChange] = str.split(':');

  path.split('.').reduce((acc, prop, index, arr) =&gt; {
    const isLastProp = arr.length === index + 1;
    if (isLastProp) {
      acc[prop] = valueToChange;
    }

    return acc[prop];
  }, obj);
}
Neither of your solutions handles the type of the replacement correctly. For instance &quot;bar.baz.foo:111222&quot; replaces foo:333444 with foo:&quot;111222&quot; where I would expect it to result in foo:111222.
Further they can handle if the replacement is an array, but not if it is an object due to the use of split(':'). You should use str.indexOf(':') together with str.substr() instead:
function replaceInObj(obj, str) {
  let splitIndex = str.indexOf(':');
  let [path, replacement] = [str.substr(0, splitIndex), str.substr(splitIndex + 1)];
  let sections = path.split('.');
  let sub = obj;
  for (var i = 0; i &lt; sections.length - 1; i++) {
    sub = sub[sections[i]];
  }

  sub[sections[i]] = JSON.parse(replacement);
  return obj;
}

Here JSON.parse() is used to interpret the value to the correct type. I don't know if the JSON api is considered as &quot;third-party&quot; in this context.

There is a more &quot;quick and dirty&quot; approach using eval:
function replaceInObj(obj, str) {
  let splitIndex = str.indexOf(':');
  let [path, replacement] = [str.substr(0, splitIndex), str.substr(splitIndex + 1)];
  eval(&quot;obj.&quot; + path + &quot;=&quot; + replacement);
  return obj;
}


Some test cases:


  let testObj = {
    bar: {
      baz: {
        foo: 333444,
        foo2: 674654
      },
      boo: {
        faa: 11
      }
    },
    fee: 333
  };

    let replacements = [
      "bar.baz.foo:111222",
      "bar.baz.foo:\"05-31-2020\"",
      "bar.baz.foo:false",
      "bar.baz.foo:\"abcdefg\"",
      "bar.baz.foo:[111222, 21341234, 234243]",
      "bar.baz.foo:{ \"aaa\": 1234, \"bbb\": \"hello world\" }"
    ];

    for (let replacement of replacements) {
      let result = replaceInObj(testObj, replacement);
      console.log(result.bar.baz.foo);
    }


function replaceInObj(obj, str) {
  let splitIndex = str.indexOf(':');
  let [path, replacement] = [str.substr(0, splitIndex), str.substr(splitIndex + 1)];
  eval("obj." + path + "=" + replacement);
  return obj;
}