Как динамически изменить значение объекта, предоставив массив его ключей? - PullRequest
0 голосов
/ 16 мая 2019

Поскольку я имею дело с относительно большим объектом, я хочу иметь возможность динамически изменять значение моего объекта, определяя «путь».

let a="x", b="y", c="z"

let objKeys = [a, b, c]

let value = 5

obj = {x: 
        {y: 
          {z: 1
          }
         }
       }


Я хочу этого добиться.

obj[a][b][c] = value;

Есть ли способ сделать это? Я попытался obj(eval(`["a"]["b"]["c"]`)) = value, но там написано, что "неверная левая часть в назначении".

Ответы [ 4 ]

2 голосов
/ 17 мая 2019

Используя массив ключей и объект, вы можете уменьшить этот объект, обращаясь к объекту с каждым ключом и возвращая конечный объект.Затем возьмите последний ключ и присвойте значение.

Этот подход добавляет новый объект в качестве значения по умолчанию для не заданных свойств.

function setValue(object, keys, value) {
    var target = keys.pop();
    keys.reduce((o, k) => o[k] = o[k] || {}, object)[target] = value;
}

var obj = { x: { y: { z: 1 } } };

setValue(obj, ['x', 'y', 'z'], 5);

console.log(obj);
1 голос
/ 16 мая 2019

Этого можно добиться с помощью функции уменьшения массива:

const objProps = ["a","b","c"]
const value = 5
const newObj = objProps.reverse().reduce((result, curProp)=> (
{
    [curProp]: result
  }
), value)

console.log(newObj)

Это "цепочка" пропеллера внутри друг друга, начиная с последнего значения в objProps. Поскольку вы хотите использовать имена в качестве индексов, используйте объект вместо массива.

РЕДАКТИРОВАТЬ: хорошо, поэтому я прочитал ваш вопрос еще раз, и, как я понял, вы не хотите создавать новый объект, но изменить значения внутри большого объекта, определив путь. Для этого взглянем на Лодаш. В этой библиотеке есть метод set, в котором вы можете указать путь к местоположению свойства и задать новое значение (https://lodash.com/docs/4.17.11#set).

1 голос
/ 16 мая 2019
let obj = {
  a: {
    b: {
      c: 'hey',
    }
  }
}

let objProps = ["a", "b", "c"];

function findValue(obj, objProps, index = 0) {
  if (index > objProps.length-1) return obj;
return findValue(obj[objProps[index]],objProps, index+1)
}

findValue(obj, objProps)
let obj = {
  a: {
    b: {
      c: 'hey',
    }
  }
}

let objProps = ["a", "b", "c"];

function assignValue(obj, objProps, newValue, index = 0) {
  console.log(obj)
  if (index >= objProps.length-1 && obj[objProps[index]]) {
    return obj[objProps[index]] = newValue;
    } else {

return assignValue(obj[objProps[index]],objProps, newValue, index+1)
  }
}

assignValue(obj, objProps, "asdsa")

0 голосов
/ 16 мая 2019

Быстрое решение, которое я создал, я уверен, что вы можете заставить его работать с eval, если вы покажете нам фактическое значение, я могу попытаться опубликовать решение с этим

Однако для этого хака:

let objProps = ['a', 'b', 'c'];
let value = ?;
let tmp;
let result = objProps.reduce((acc, curr) => {
    let tmp_v2 = acc;
    while (Object.keys(tmp).length > 0) {
        tmp_v2 = tmp[Object.keys(tmp_v2)[0]]
    }
    tmp_v2[curr] = {};
    tmp = tmp_v2;
    return acc
}, {})
tmp.c = value;

сейчас result будет выглядеть так:

{
  "a": {
    "b": {
      "c": value
    }
  }
}

как хотел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...