1

i use this script for depth search in an object. I use a string to get or set the value in an object. I think code explain everything:

function _SetObjectByName(obj, prop, value) {
  try {
    if (typeof obj === 'undefined') {
      return false;
    }
  
    let _index = prop.indexOf('.');
    if (_index > -1) {
      let _NestedObject = prop.substring(0, _index);
      let _newProp = prop.substr(_index + 1);
      if (_NestedObject.includes('[')) {
        let ArrayElement = _NestedObject.match(/\d+/)[0];
        _NestedObject = _NestedObject.substring(0, _NestedObject.indexOf('['));
        return _SetObjectByName(obj[_NestedObject][parseInt(ArrayElement, 10)], _newProp, value);
      }
      return _SetObjectByName(obj[_NestedObject], _newProp, value);
    }
    obj[prop] = value;
  }
  catch(err) {
    console.log('error');
  }
}

My Object:

let Object5 = {
  Bool: false,
  Number1: 0,
  Number2: 0,
  Number3: 0,
  Number4: 0,
  Number5: 0,
  Number6: 0,
  Number7: 0
  };

let Object4 = {
  Text: '',
  ObjectA: Object.assign({}, Object5),
  ObjectB: Object.assign({}, Object5),
  ObjectC: Object.assign({}, Object5),
  ObjectD: Object.assign({}, Object5),
};

let Object3 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object4), 
             Object.assign({}, Object4)
  ]
};

let Object2 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3)
  ]
};

let Object1 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2)
  ]
};

So now if i try this:

_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].Text','Test1')
_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[1].Text','Test2')

it works as expected -> different values, but if do this:

_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].ObjectA.Number1',1)

i have a problem. All Array Elements of ObjectA[0].ObjectA[0].ObjectA[X].ObjectA.Number1 are 1. Can someone explain me why?

  • i ran the script for the Number1 case and i just get added another Number1 (with value 1) to the Object4...so i get a different behaviour than you and im not sure why – GreenChicken Aug 16 '23 at 10:14

1 Answers1

0

Just generate a function to assign a value to any path in an obj.

function _SetObjectByName(obj, path, value){
  const fn = new Function('obj, path, value', `obj.${path} = ${JSON.stringify(value)}`);
  fn(obj, path, value);
}

_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].Text','Test1')
_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[1].Text','Test2')
_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].ObjectA.Number1',1)

$result.textContent = JSON.stringify(Object1, null, 4);
<pre id="$result"></pre>
<script>
let Object5 = {
  Bool: false,
  Nummer1: 0,
  Nummer2: 0,
  Nummer3: 0,
  Nummer4: 0,
  Nummer5: 0,
  Nummer6: 0,
  Nummer7: 0
  };

let Object4 = {
  Text: '',
  ObjectA: Object.assign({}, Object5),
  ObjectB: Object.assign({}, Object5),
  ObjectC: Object.assign({}, Object5),
  ObjectD: Object.assign({}, Object5),
};

let Object3 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object4), 
             Object.assign({}, Object4)
  ]
};

let Object2 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3)
  ]
};

let Object1 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2)
  ]
};
</script>

Also note that you have the same objects in several places, so changing a value in them changes the value in all object references.

Object.assign() doesn't help since you have object properties, it would help only with scalar properties.

If you make a clone with JSON.stringify() it would work like you want:

function _SetObjectByName(obj, path, value){
  const fn = new Function('obj, path, value', `obj.${path} = ${JSON.stringify(value)}`);
  fn(obj, path, value);
}

_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].Text','Test1')
_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[1].Text','Test2')
_SetObjectByName(Object1,'ObjectA[0].ObjectA[0].ObjectA[0].ObjectA.Number1',1)

$result.textContent = JSON.stringify(Object1, null, 4);
<pre id="$result"></pre>
<script>
let Object5 = {
  Bool: false,
  Nummer1: 0,
  Nummer2: 0,
  Nummer3: 0,
  Nummer4: 0,
  Nummer5: 0,
  Nummer6: 0,
  Nummer7: 0
  };

let Object4 = {
  Text: '',
  ObjectA: Object.assign({}, Object5),
  ObjectB: Object.assign({}, Object5),
  ObjectC: Object.assign({}, Object5),
  ObjectD: Object.assign({}, Object5),
};

let Object3 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object4), 
             Object.assign({}, Object4)
  ]
};

let Object2 = {
  Text: '',
  ObjectA: [ Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3), 
            Object.assign({}, Object3)
  ]
};

let Object1 = JSON.parse(JSON.stringify({
  Text: '',
  ObjectA: [ Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2), 
                Object.assign({}, Object2)
  ]
}));
</script>
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17
  • Thanks for your support. I see there are much easier ways to access an object with strings. What is the correct way to copy objects in an object? Some Object change by time and i want to make an edit in the most simplest way. – noname028743 Aug 16 '23 at 10:15
  • @noname028743 the second snippet shows how to deep clone an object with `JSON.stringify()`. you could also use `structuredClone()` – Alexander Nenashev Aug 16 '23 at 10:18
  • function _GetObjectByName(obj, path) { const fn = new Function('obj, path', `return obj.${path}`); return fn(obj, path); } to return the Object. – noname028743 Aug 16 '23 at 10:50
  • @noname028743, yes, also possible. and modify its property – Alexander Nenashev Aug 16 '23 at 12:11
  • can you recommend something to compare 2 objects with each other? it should be called deep object search. i tried lodash but i always get only the first level as return value. I could also start a new question but i think you are a really smart guy ;) – noname028743 Aug 17 '23 at 09:04
  • @noname028743 https://stackoverflow.com/questions/76512735/javascript-check-if-arrays-within-an-array-are-the-same/76513007#76513007 – Alexander Nenashev Aug 17 '23 at 09:26