В JavaScript есть ли более простой способ проверить, существует ли свойство свойства?
Есть ли простой способ изначально определить, существует ли глубокое свойство внутри объекта в JavaScript? Например, мне нужно получить доступ к следующему свойству:
var myVal = appData.foo.bar.setting;
Но есть вероятность, что foo, foo.bar или foo.bar.setting еще не определены. В Groovy мы можем сделать что-то вроде этого:
def myVal = appData?.foo?.bar?.setting
Есть ли аналогичный способ сделать это в JavaScript, без необходимости писать пользовательскую функцию или вложенные операторы if? Я нашел этот ответ, чтобы быть полезным, но надеялся, что был более элегантный и менее обычай.
Ответы
Ответ 1
Я считаю это очень удобным:
var myVal = (myVal=appData) && (myVal=myVal.foo) && (myVal=myVal.bar) && myVal.settings;
Если свойство существует, будет предпринята попытка выполнить следующую часть последовательности.
Если выражение перед &&
оценивается как false, следующая часть выражения не будет проверяться. Если какой-либо из myVal.appData.foo.bar.settings
не определен, значение myVal
(undefined
(будет оцениваться до false
.
Ответ 2
Извините, это не здорово:
var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.setting;
Другая опция:
try {
var myVal = appData.foo.bar.setting;
} catch (e) {
var myVal = undefined;
}
. оператор не предназначен для доступа к таким объектам. Вероятно, использование функции было бы хорошей идеей.
Ответ 3
Я нахожу другие подходы немного огромными. Итак, каков был бы главный недостаток следующего подхода:
// Pass the path as a string, parse it, and try to traverse the chain.
Object.prototype.pathExists = function(path) {
var members = path.split(".");
var currentMember = this;
for (var i = 0; i < members.length; i++) {
// Here we need to take special care of possible method
// calls and arrays, but I am too lazy to write it down.
if (currentMember.hasOwnProperty(members[i])) {
currentMember = currentMember[members[i]];
} else {
return false;
}
}
return true;
}
В принципе, мы определяем метод объекта (не обязательно), и этот метод берет путь к вложенному объекту и возвращает подтверждение существования, например appData.pathExists("foo.bar.setting");
EDIT:
Проверить object[prop] == undefined
не семантически корректно, так как он вернет false, даже если свойство определено, хотя его значение равно undefined
; поэтому я использую hasOwnProperty
, чтобы проверить, определено ли свойство. Это может быть не важно, если нужно просто получить значение.
Ответ 4
Если, после:
var myVal = appData.foo && appData.foo.bar && appData.foo.bar.setting;
myVal
не undefined
, он будет удерживать значение appData.foo.bar.setting
.
Ответ 5
Вы можете попробовать это
var x = {y:{z:{a:'b'}}}
x && x.y && x.y.z && x.y.z.a //returns 'b'
Это не так хорошо, как выражение groovy, но оно работает. Оценка прекращается после появления первой переменной undefined.
Ответ 6
var product = ...,
offering = (product||{}).offering,
merchant = (offering||{}).merchant,
merchantName = (merchant||{}).name;
if (merchantName)
displayMerchantName(merchantName);
http://osteele.com/archives/2007/12/cheap-monads
Ответ 7
Я только что приготовил это, чтобы он не работал точно, я также включил два тестовых примера.
function hasPropertyChain(o, properties) {
var i = 0,
currentPropertyChain = o;
if(!o) {
return false;
}
while(currentPropertyChain = currentPropertyChain[properties[i++]]);
return i - 1 === properties.length;
}
alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c'])); // true
alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c', 'd'])); // false