JS обновляет вложенный объектный ключ строкой имен ключей, объединяясь с "." - PullRequest
0 голосов
/ 21 октября 2018

Допустим, у меня есть этот объект:

var obj = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

Теперь я хочу обновить ключ title, используя следующую строку (обратите внимание, у меня есть строка, не актуальнаяпеременная) У меня есть: let myString = "level1.level2.level3.title"; // note - myString value comes from $http method or something

Может быть, что-то вроде этого:

obj[myString] = "super-winner";

К сожалению, выше не работает.

Кроме того - иногда мне нужно обновитьнеопределенный объект, поэтому мне нужно что-то, чтобы объект был определен с новым пустым объектом.

Например, если у меня есть следующий объект:

var obj = {
  level1 : {}
  }
}

Я все еще хочу изменитьobj с указателем level3.winner, как указано выше.

Напоминание: obj[myString] = "super-winner";

Как я могу это сделать?

Ответы [ 4 ]

0 голосов
/ 21 октября 2018

Используется " уменьшение " для достижения желаемого результата.Создана функция «updateValue», в которой вы можете передать obj-объект для изменения, str-путь свойства для изменения, значение-значение, которое будет назначено в пути свойства

var obj1 = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

var obj2 = { level1: {} }

var obj3 = {
  level1 :{
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
}

function updateValue(obj, str, value) {
let props = str.split('.'), arrIndex = -1
props.reduce((o,d,i) => ( 
                         arrIndex = d.indexOf('[') > -1 && d[d.indexOf('[') + 1],
                          arrIndex && (d = d.slice(0, d.indexOf('['))),
                           i == props.length - 1 
                              ? o[d] = value 
                              : (o[d] = o[d] || {}, (arrIndex && (Array.isArray(o[d]) || (o[d] = [o[d]]))), arrIndex && o[d][arrIndex] || o[d])
                        )
                , obj)
}

updateValue(obj1, 'level1.level2.level3.title', 'abcd')
updateValue(obj2, 'level1.level2.level3.title', 'abcd')
updateValue(obj3, 'level1.level2[0].title', 'abcd')

console.log(obj1)
console.log(obj2)
console.log(obj3)
0 голосов
/ 21 октября 2018

Вы можете использовать .set функцию lodash https://lodash.com/docs#set

ex: _.set(obj, 'level1.level2.level3.title', 'super-winner');

Или использовать функцию синтаксиса ES6:

var str = 'level1.level2.level3.title';
str.split('.').reduce((p, c, index) => {
    if (index === str.split('.').length - 1) {
        if (typeof p[c] !== "object") { // string, number, boolean, null, undefined
            p[c] = 'super-winner'
        }
        return p[c];
    } else {
        if (!p[c] || typeof p[c] !== 'object') {
            p[c] = {};
        }
        return p[c];
    }
}, obj)

console.log(obj);
0 голосов
/ 21 октября 2018

Это можно сделать вручную, многократно индексируя структуру объекта и создавая новые объекты по мере необходимости по пути к ключу назначения:

const updateField = (o, path, entry) => {
  path = path.split(".");
  let curr = o;
  
  while (path.length > 1) {
    const dir = path.shift();    
    const parent = curr;
    curr = curr[dir];

    if (undefined === curr) {
      parent[dir] = {};
      curr = parent[dir];
    }
  }
  
  if (path.length === 1) {
    curr[path.shift()] = entry;
  }
  
  return o;
};

var obj = {
  level1 : {
    level2: {
      level3: {
        title: "winner"
      }
    }
  }
};

console.log(JSON.stringify(updateField(obj, "level1.level2.level3.title", "super-winner"), null, 2));
console.log(JSON.stringify(updateField({}, "level1.level2.level3.title", "super-winner"), null, 2));
0 голосов
/ 21 октября 2018

Это работает

const obj = {
   // level1: {
    //     level2: {
    //         level3: {
    //             title: "winner"
    //         }
    //     }
    // }
}

const myString = "level1.level2.level3.title"; // note - myString value comes from $http method or something

const title = 'super-winner'

myString.split('.')
    .reduce(
        (acc, curr) => {
            if (acc[curr] === undefined && curr !== 'title') {
                acc[curr] = {}
            }

            if (curr === 'title') {
                acc[curr] = title
            }

            return acc[curr]
        }, obj
    );

console.log(obj) // {"level1":{"level2":{"level3":{"title":"super-winner"}}}}

Это решение с нулевой зависимостью, то есть вам не нужно использовать lodash или что-то еще, что увеличивает размер вашего приложения.

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