Шаблон, чтобы избежать длинных цепочек точек
При доступе к вложенным объектам с использованием точечной нотации мне всегда нужно убедиться, что предыдущий объект существует, что становится довольно утомительным.
Я в основном хочу избежать долго, если цепочки вроде
if (a && a.b && a.b.c && a.b.c[0] ... ) { v = a.b.c[0]; }
Единственное, что я могу придумать, это использовать попытку catch.
var v; try { v = a.b.c[0].d.e; } catch (e) {}
Есть ли лучший шаблон для этого?
Ответы
Ответ 1
Я думаю, что у вас уже есть два самых красивых решения.
Но обратите внимание, что для чего-то вроде, скажем, obj.obj.string.length
ваше первое решение не сработает, если string === ""
. Так как пустая строка ложна, она отключит охрану &&
.
Но, говоря о строках, вы можете сделать что-то вроде:
function getNestedProperty(obj, propChain) {
var props = propChain.slice(0), prop = props.shift();
if(typeof obj[prop] !== "undefined") {
if(props.length) {
return getNestedProperty(obj[prop], props);
} else {
return obj[prop];
}
}
}
var v = getNestedProperty(a, ["b", "c", 0, "d", "e"]);
Да... не слишком красиво: P
Я бы сказал, что из предлагаемых решений try...catch
, вероятно, самый простой способ пойти
Ответ 2
Как насчет этого:
var hasProperty = function (object, property) {
var properties = property.split('.'),
temp = object;
while (temp && properties.length) {
temp = temp[properties.shift()];
}
return !!temp;
};
а затем используйте его как:
if (a && hasProperty(a, 'b.c.0' ) { v = a.b.c[0]; }
Ответ 3
Это скорее зло, но это должно работать и не выглядит слишком ужасным:
var i = !a ? null : !a.b ? null : !a.b.c ? null : !a.b.c.d ? a.b.c.d.e;
Причиной для !
является инвертирование тестового флага, чтобы случай успеха был последним выражением в ?:
. Это позволяет нам объединить их вместе.
Проверяйте приоритет оператора, если вы хотите сделать это по-настоящему (я сделал некоторые очень простые тесты, и я думаю, что я понял это правильно). И ожидайте, что люди будут указывать и смеяться, если они видят это в вашем коде.