Как я могу получить доступ и изменить значение в объекте с массивом ключей

#javascript #javascript-objects

Вопрос:

 const object = {
    key1: 'example_key1',
    key2: {
        key3: 'example_key2'
    }
}

const string = 'key1'
const array = ['key2', 'key3']

object[string] = 'foo' // Work
object[array] = 'bar' // Dont work
 

Как я могу получить доступ к объекту и изменить его с помощью массива ключей?

Я пробовал loadash.get , но он может только получать значения, а не изменять их.

Комментарии:

1. Что вы ожидаете object[array] вернуть?

2. Объект[индекс] — это то, что вам нужно, поэтому, если вы дадите объект[массив[0]], это сработает. Но если вы хотите, чтобы все значения, которые вам нужны, были инициализированы в bar, тогда это отдельная история

3. Будет ли массив всегда иметь длину 2 или он может быть длиннее ?

4. Да, массив может измениться. И быть длиннее или короче.

Ответ №1:

Вам нужно сделать что-то вроде следующего:

 function set(obj, path, value) {
  var schema = obj
  var len = path.length
  for(var i = 0; i < len - 1; i  ) {
    var elem = path[i]
    if (!schema[elem] ) schema[elem] = {}
    schema = schema[elem]
  }

  schema[path[len-1]] = value
}
 

И тогда вы могли бы использовать его следующим образом:

 set(object, array, 'someText')
 

С помощью функции, подобной описанной выше set , вы можете обновить объект, передав массив вложенных ключей и новое значение.

Ответ №2:

Вы могли бы сделать что-то вроде:

 const object = {
    key1: 'example_key1',
    key2: {
        key3: 'example_key2'
    }
}

const string = 'key1'
const array = ['key2', 'key3']

console.log(object[array[0]][array[1]]) 

Редактировать

Первое решение-статическое. Приведенное ниже решение является более динамичным:

 const object = {
    key1: 'example_key1',
    key2: {
        key3: 'example_key2'
    }
}

const object2 = {
    key1: 'example_key1',
    key2: {
        key3: {
           key4: "example_key3"
        }
    }
}


const string = 'key1'
const array = ['key2', 'key3']

let nestedObj = undefined;
array.forEach(val => {
   if (nestedObj) nestedObj = nestedObj[val];
   else nestedObj = object[val];
})
console.log(nestedObj)

const array2 = ['key2', 'key3', 'key4']

let nestedObj2 = undefined;
array2.forEach(val => {
   if (nestedObj2) nestedObj2 = nestedObj2[val];
   else nestedObj2 = object2[val];
})
console.log(nestedObj2) 

Комментарии:

1. что это ты здесь делаешь?

2. Это работает, но если я изменю массив, мне нужно будет добавить его вручную array[2] .

3. @PowerKuu Я добавил динамическое решение к своему ответу =)

Ответ №3:

Вы можете создать рекурсивную функцию и проверить, существует ли ключ от объекта в массиве, если да, то измените значение ключа в объекте

 const object = {
  key1: 'example_key1',
  key2: {
    key3: 'example_key2'
  },
  key3: 'someVal'
}

const array = ['key2', 'key3']

function doRecursion(obj) {
  for (let keys in obj) {
    if (array.includes(keys)) {
      console.log(typeof obj[keys])
      if (typeof obj[keys] === 'object') {
        doRecursion(obj[keys])
      } else {
        obj[keys] = 'bar';
      }
    } else {
      console.log(keys)
    }

  }
  return obj
};

console.log(doRecursion(object)); 

Ответ №4:

Я думаю, что здесь рекурсия облегчит задачу

 function get(obj, keys) {
  if(typeof keys === 'string') {
    return obj[keys];
  }
  const key = keys.shift();
  return keys.length ? get(obj[key], keys) : obj[key];
}

const object1 = {
    key1: 'example_key1',
    key2: {
        key3: 'example_key2'
    }
}

const object2 = {
    key1: 'example_key1',
    key2: {
        key3: {
           key4: "example_key3"
        }
    }
}

const string = 'key1'
const array1 = ['key2', 'key3'];
const array2 = ['key2', 'key3', 'key4'];

console.log(get(object1, string));
console.log(get(object1, array1));
console.log(get(object2, array2));