Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

113
Vistas
Update a JavaScript object recursively using values from another object

I would like to add some data to a nested JavaScript object, however I do not know how much of the object tree already exists. I want to add the structure if it is not there, but also keep the same information if it is there tagged with some other default data.

Ideally I don't want to use a third party library for this.

In my example I have the following object structure, there will be an endless combination of these available, so it needs to generate the structure for me if it does not already exist.

{
  level1: {
    level2: {
      level3: {
        property1: 'test'
      }
    }
  }
}

I want to be able give this some values, create the structure - if the structure is there, add some default values and if not create the structure with defaults.

I have the following, which does the job, but it looks very messy to me, I was wondering if there was a better way to achieve this?

const updateNestedObject = (obj, level1, level2, level3, defaultProps) => {
  if (obj && obj[level1] && obj[level1][level2] && obj[level1][level2][level3]) {
    obj[level1][level2][level3] = { ...defaultProps, ...obj[level1][level2][level3] }
  } else if (obj && obj[level1] && obj[level1][level2] && !obj[level1][level2][level3]) {
    obj[level1][level2][level3] = defaultProps
  } else if (obj && obj[level1] && !obj[level1][level2]) { 
    obj[level1][level2] = { [level3]: defaultProps }
  } else if (obj && !obj[level1]) { 
    obj[level1] = { [level2]: { [level3]: defaultProps } }
  } else {
    obj = { [level1]: { [level2]: { [level3]: defaultProps } } }
  }
  return obj
}
about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

You could do something like this, where you loop over the keys and traverse the object level by level. Each loop we set an outside variable - level - to the current one, so we don't have to use the previous keys to reach the current level. i.e., we avoid having to do obj[ level1 ][ level2 ][ level3 ] = ..., instead, we can just do level = ...

In this way, I'd say it's better to pass a single parameter keys, which is an array. With this, you aren't limited to exactly 3 nested keys, but can pass any number you want to.

const updateNestedObject = ( obj, keys, defaultProps ) => {
  let level = obj;
  for ( let i = 0; i <= keys.length-1; i++ ) {
    let key = keys[ i ];

    if ( i === keys.length-1 ) {
      level[ key ] = { ...defaultProps };
      return;
    }

    if ( !level[ key ] ) {
      level[ key ] = {};
    }

    level = level[ key ];
  }
};

const object = {};
updateNestedObject( object, [ "foo", "bar", "baz" ], { property: "test" } )
console.log( object );

const object2 = { foo: { bar: {} } };
updateNestedObject( object2, [ "foo", "bar", "baz" ], { property: "test" } )
console.log( object2 );

const object3 = { foo: { bar: {} } };
updateNestedObject( object3, [ "foo", "bar" ], { property: "test" } )
console.log( object3 );

Note that this does change the object in-place.

about 4 years ago · Juan Pablo Isaza Denunciar

0

This could be done via recursion. Below is an outline of how to implement it (not tested for all cases):

function mergeRecursive(targetObject, sourceObject) {
  Object.keys(sourceObject).forEach(function(key) {
    if (typeof sourceObject[key] === "object") {
      if (targetObject[key] === undefined) {
        targetObject[key] = {};
      }
      mergeRecursive(targetObject[key], sourceObject[key]);
    } else {
      targetObject[key] = sourceObject[key];
    }
  });
}
let foo = {
  "level1": {
    "bar": "baz"
  }
};
let bar = {
  level1: {
    level2: {
      level3: {
        property1: "test"
      }
    }
  }
};
mergeRecursive(foo, bar);
console.log(foo);

about 4 years ago · Juan Pablo Isaza Denunciar

0

A minor variant of a setPath function I use often would do this in a fairly straightforward manner:

const mixDeep = ([p, ...ps]) => (v) => (o) =>
  p == undefined ? v : Object .assign (
    Array .isArray (o) || Number .isInteger (p) ? [] : {},
    {...o, [p]: ps .length ? mixDeep (ps) (v) ((o || {}) [p]) : {...v, ...(o || {}) [p]}},
  ) 

const myFunc = 
  mixDeep (['level1', 'level2', 'level3']) ({some: 'default', props: 'here'}) 

console .log (myFunc ({foo: 'bar'}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux'}}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux', level2: {corge: 'grault'}}}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux', level2: {corge: 'grault', level3: {garply: 'waldo'}}}}))
.as-console-wrapper {max-height: 100% !important; top: 0}

setPath sets the value at the path, building intermediate nodes as necessary. mixDeep mixes the value into the value at the end of the path, again building whatever intermediate nodes are missing.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda