Мне было интересно, возможно ли получить доступ к значению внутри вложенного объекта с помощью только одной строки. Предположим, у меня есть такой объект:

skill: {
    skillDetails: {
        developerDetails: {
            developerName: "mr. developer"
        }
    }
}

Есть ли способ, которым я могу сделать что-то вроде этого, чтобы получить значение через «путь JSON»: skill["skillDetails.developerDetails.developerName"]?

Я спрашиваю об этом потому, что пытаюсь передать объект key & в функцию (которую я не могу изменить), которая по существу возвращает object[key]

Не уверен, что это возможно, поэтому я подумал, что попросил бы вас, ребята, дать совет

Благодарность!

3
Tim 7 Дек 2018 в 03:43

3 ответа

Лучший ответ

Не существует встроенного метода, однако простое решение этого (которое не требует сторонней библиотеки) может быть достигнуто с помощью split() и reduce() следующим образом:

var skill = {
  skillDetails: {
    developerDetails: {
      developerName: "mr. developer"
    }
  }
}

var path = "skillDetails.developerDetails.developerName";

var value = path
.split('.') // Split path into parts by '.'
.reduce((obj, part) => obj ? obj[part] : undefined, skill); // Extract value via reduction

console.log(value)
2
Dacre Denny 7 Дек 2018 в 00:48

К сожалению, быстрого встроенного метода для этого нет - вам понадобится вспомогательная функция.

lodash поддерживает это с помощью _.get(obj, property).

Из документов:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'
2
Elliot B. 7 Дек 2018 в 00:46

Стандарт де-факто для простого JS заключается в использовании Array.reduce, поскольку используя его аккумулятор, он позволяет вам «идти по пути» до тех пор, пока вы не доберетесь до значения, но часто используется тот случай, когда на пути у вас может быть функция, которая игнорируется. Вот пример:

var obj = {
  foo: {
    bar: {
      fooBar: "BARFOO",
      foo: function() { return { c: 'BAR' }}
    }
  }
}

const get = (obj, path) => path.split('.').reduce((r,c) => {
  return r ? typeof r === 'function' ? r()[c] : r[c] : undefined
}, obj)

console.log(get(obj, 'foo.bar.fooBar'))
console.log(get(obj, 'foo.bar.foo'))
console.log(get(obj, 'foo.bar.foo.c'))

Как вы можете видеть, если вы хотите получить фактическое значение foo.bar.foo.c, вам нужно пройти через функцию и выполнить ее ... теперь все это "пропущено", если вы решите использовать _.result из lodash:

var obj = {
  foo: {
    bar: {
      fooBar: "BARFOO",
      foo: function() { return { c: 'BAR' }}
    }
  }
}

console.log(_.result(obj, 'foo.bar.fooBar'))
console.log(_.result(obj, 'foo.bar.foo'))
console.log(_.result(obj, 'foo.bar.foo.c'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Что-то, что нужно держать в середине, наряду с _.get, который принесет только ваши ценности и не будет проходить через функции и _.has, которые будут возвращать логическое значение, если { {X2}} действителен или нет.

1
Akrion 7 Дек 2018 в 01:28