Доступ к свойству объекта с динамически вычисляемым именем
Я пытаюсь получить доступ к свойству объекта, используя динамическое имя. Это возможно?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // Идея в том, чтобы получить доступ к something.bar и получить "Foobar!"
5 ответ(ов)
Вот моё решение:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
Примеры использования:
resolve("document.body.style.width")
// или
resolve("style.width", document.body)
// также можно использовать индексы массивов
// (someObject был определён в вопросе)
resolve("part.0.size", someObject)
// возвращает null, если промежуточные свойства не определены:
resolve('properties.that.do.not.exist', {hello: 'world'})
Если у вас есть дополнительные вопросы или требуется объяснение, не стесняйтесь спрашивать!
В JavaScript мы можем получить доступ к свойствам объекта двумя способами:
- с использованием точечной нотации:
foo.bar
- с использованием квадратных скобок:
foo[someVar]
илиfoo["string"]
Однако только второй способ позволяет обращаться к свойствам динамически.
Вот пример:
var foo = { pName1: 1, pName2: [1, { foo: 'bar' }, 3], /* другие свойства */ }
var name = "pName";
var num = 1;
foo[name + num]; // вернет 1
// --
var a = 2;
var b = 1;
var c = "foo";
foo[name + a][b][c]; // вернет 'bar'
В этом примере мы создаем объект foo
, имеющий несколько свойств. Используя переменные для создания имен свойств, мы можем динамически получать доступ к ним через квадратные скобки, что дает большую гибкость при работе с объектами.
Вы можете достичь этого несколькими разными способами.
let foo = {
bar: 'Hello World'
};
foo.bar; // Доступ через точечную нотацию
foo['bar']; // Доступ через квадратные скобки
Квадратная нотация особенно мощная, так как позволяет вам обращаться к свойствам на основе переменных:
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop]; // Доступ через переменную
Это можно расширить до перебора всех свойств объекта. Это может показаться избыточным из-за более новых конструкций JavaScript, таких как for ... of ...
, но помогает иллюстрировать случай использования:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop of Object.getOwnPropertyNames(foo)) {
console.log(foo[prop]); // Выводим значения всех свойств
}
Обе нотации (точечная и квадратная) также работают как ожидается для вложенных объектов:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz; // Доступ через точечную нотацию
foo['bar']['baz']; // Доступ через квадратные скобки
foo.bar['baz']; // Смешанный доступ
foo['bar'].baz; // Смешанный доступ
Деструктуризация объектов
Мы также можем рассмотреть деструктуризацию объектов как способ доступа к свойству объекта, однако с использованием следующего синтаксиса:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
let prop = 'last';
let { bar, baz, [prop]: customName } = foo;
// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
Таким образом, вы получаете доступ к свойствам объекта несколькими способами, в зависимости от ваших потребностей и предпочтений.
Вы можете сделать это следующим образом, используя метод get
из библиотеки Lodash:
_.get(object, 'a[0].b.c');
Этот метод позволяет безопасно извлекать значения из объектов, даже если промежуточные свойства отсутствуют. Если путь не существует, _.get
вернет undefined
вместо того, чтобы выдать ошибку.
В вашем случае вы правильно подошли к задаче, пытаясь получить доступ к вложенным свойствам объекта при помощи массива ключей. Это действительно сложно сделать с помощью нотации точек, особенно когда вам приходится использовать строки для обозначения каждого уровня вложенности. Ваше решение с использованием функции getText
выглядит очень удобно.
Функция, которую вы написали, последовательно проходит по массиву ключей и использует их для доступа к вложенным свойствам объекта. В результате, вашим задачей становится извлечение значения по переданным ключам.
Ваш пример кода иллюстрирует это довольно хорошо:
function getText(selectionArray, obj) {
selectionArray.forEach(key => {
obj = obj[key];
});
return obj;
}
Такое решение позволяет динамически получать доступ к значениям, что может быть весьма полезным, когда структура объекта известна заранее, но конкретные ключи могут быть переданы извне.
С точки зрения использования вашей функции, вы можете легко извлечь текст, как показано в ваших примерах:
console.log(getText(["audioPlayer", "controls", "stop"], locs)); // возвращает 'stop'
console.log(getText(["audioPlayer", "heading"], locs)); // возвращает 'Use controls to start and stop audio.'
Если вам необходимо сделать ваш код еще более устойчивым к ошибкам, вы можете рассмотреть возможность добавления проверки существования ключа в объекте на каждом шаге, чтобы избежать ошибок, если ключ не найден. Например:
function getText(selectionArray, obj) {
for (let key of selectionArray) {
if (obj && typeof obj === 'object' && key in obj) {
obj = obj[key];
} else {
return undefined; // или можно выбросить ошибку
}
}
return obj;
}
Такое обновление позволит вашей функции быть более надежной при работе с объектами, которые могут не содержать всех переданных ключей. Надеюсь, это поможет!
Как удалить свойство из объекта JavaScript?
Сортировка свойств объекта по значениям
Проверка существования вложенного ключа объекта JavaScript
Как удалить все дубликаты из массива объектов?
Почему null является объектом и в чем разница между null и undefined?