假设我有一个JavaScript对象:
var obj = {};
obj.computers = {};
obj.computers.favorite = "Commodore 64";
obj.computers.popular = "Apple";
现在,我可以轻松检查null:
if(obj != 'undefined' && obj != null) {
if(obj.computers != 'undefined' && obj.computers != null)) {
.....
正如您所看到的,如果我需要查看是否已设置obj.computers.favorite
,我必须在那里嵌套一些条件逻辑。我们的一些物体的深度为3,4,5级。
这是我希望能够做到的:
var fav = obj.computers.favorite || 'Unknown';
但我意识到我需要在某种方法中包装它。类似的东西:
var fav = getValueOrDefault(obj.computers.favorite, 'Unknown');
建议表示赞赏。
由于
修改
我检查'undefined'实际上并不是我使用的。在提出这个问题时,我只是想到了。洛尔
但我想知道,我可以在try / catch中包装并在异常时抛出默认值吗?
function(obj, default) {
try {
if(obj != null) {
return obj;
} else {
return default;
}
} catch(ex) {
return default;
}
}
另外,感谢Shusi指出冗余的变种。
答案 0 :(得分:6)
你真的可以写:
(obj && obj.computers && obj.computers.favorite) || 'Unknown'
答案 1 :(得分:3)
您可以使用帮助功能执行此操作。如果我正确理解您的问题,您的对象可能具有任意深层对象,并且您希望访问这些任意嵌套属性而不会使代码混乱。我构建了一个Nested
函数,它可以get()
设置任意属性,如果没有,则为默认属性。
var Nested = function() {};
// prop is a dot-separated path like "foo.bar.baz"
Nested.prototype.get = function(prop, _default) {
var current = this;
$.each(prop.split("."), function(i, e) {
current = current[e] || undefined;
if (current == undefined)
return false;
});
return current || _default;
}
然后你可以编写像这样的代码
var fav = obj.get("computers.favourite", "Linux");
// this emulates
var fav = obj.computers.favourite || "Linux"; // throws error
正如您所看到的,打字并不多。当然,它不像常规Javascript ...... Here is the fiddle。
答案 2 :(得分:3)
我写这篇文章是为了帮助您处理一个问题:“我需要查看obj.computers.favorite是否已设置”。
Object.prototype.isset = function (/* string */ full_path)
{
var props = full_path.split('.');
var self = this; /* note that self is usually the window object */
for (var ii = 0; ii < props.length; ++ii)
{
var prop = props[ii];
var hasMoreComing = ii < props.length - 1 ? true : false;
if (self[prop] !== null && typeof self[prop] === 'object' && hasMoreComing)
{
self = self[prop];
continue; // Move up one level.
}
else if (hasMoreComing)
return false; // ..because user queries a subproperty of a value type
return self.hasOwnProperty(prop);
}
};
<强>测试码:强>
var test = {};
test.kuk = {};
console.log( test.isset('kuk') ); // Prints true.
test.kuk.fitta = {};
console.log( test.isset('kuk.fitta') ); // Prints true.
test.kuk.fitta = null;
console.log( test.isset('kuk.fitta') ); // Prints true.
test.kuk.fitta = undefined;
console.log( test.isset('kuk.fitta') ); // Prints true
delete test.kuk.fitta;
console.log( test.isset('kuk.fitta') ); // Prints false
test.kuk.fitta = 123;
console.log( test.isset('kuk.fitta.doesnt.exist') ); // Prints false
答案 3 :(得分:1)
以下函数将字符串作为参数并返回对象(如果存在)
function getValueOrDefault(str , obj, deflt){
var a = str.split("."); o = obj;
for(var i =0; i < a.length; i++){
o = obj[a[i]];
if(!o){
return deflt;
}
}
return o;
}
var obj = {};
obj.computers = {};
obj.computers.favorite = "Commodore 64";
obj.computers.popular = "Apple";
getValueOrDefault('computers.favorite', obj, 'Unknown');
注意:在为对象分配属性时,不得使用var。 var obj.computers.favorite
是SYNTAX错误。
答案 4 :(得分:1)
不幸的是,没有一种超级简单的方法来解决这个问题,但是您不需要检查null和undefined。因为null和undefined都是假的,你可以这样做:
if (obj && obj.computers) {
var fav = obj.computers.favorite || 'unknown';
}
它实际上并没有解决你的抱怨,但它比你的想法痛苦少。
答案 5 :(得分:1)
optional chaining operator是处理此问题的最新方法:
python manage.py collectstatic
将此与nullish coalescing operator结合使用,您可以精确执行最初要求的操作:
let favorite = obj?.computers?.favorite;
请注意,虽然这些运算符都尚未得到普遍支持。
答案 6 :(得分:0)
您还可以使用 JavaScript ES5 reduce
函数进行此操作:
function get(root, member) {
return member.split('.').reduce((acc, value) => {
return (acc && typeof acc[value] !== 'undefined') ? acc[value] : undefined
}, root);
}
它从成员字符串中组成一个数组,然后随着成员的减少,累加器逐渐遍历对象。
即使是数组,也可以像这样使用它:
let obj = {
computers : {
favorite : "Commodore 64",
popular : "Apple",
list: [
{
sn : "TDGE52343FD76",
price: "9867.99",
options: {
fanless: true
}
}
]
}
}
get(obj, 'computers.popular');
// => "Apple"
get(obj, 'computers.list.0.sn');
// => "TDGE52343FD76"
get(obj, 'computers.list.0.options.fanless');
// => true
get(obj, 'computers.list.0.options.runsWithoutEletricity');
// => undefined
get(obj, 'computers.list.0.options.runsWithoutEletricity') || "too bad..." ;
// => "too bad..."
有一个safely traverse js object的codepen