的Javascript获取对象的属性和子属性

问题描述:

我试图访问一个对象的属性是这样的:的Javascript获取对象的属性和子属性

var scope1 = {a: {value: 25}}; 
var scope2 = undefined; 

var v1 = scope1.b.value || 0; // TypeError: Cannot read property 'value' of undefined 
var v2 = scope2.b.value || 0; // TypeError: Cannot read property 'value' of undefined 

apparentl的||操作员不给我我想要的。我知道我可以做以下代替

var vv2 = (scope1 && scope1.b ? scope1.b.value : 0); 

但是这使得代码确实冗长的...所以任何人都知道,如果有更简单的方法做我想做的事?谢谢。

通常的答案是&&操作:

var v1 = scope1.b && scope1.b.value || 0; 

...因为喜欢||&&curiously powerful&&评估左侧操作数,如果它的falsey,采用的是falsey值作为其结果;如果左侧操作数值为真,则&&将计算右侧操作数并将该值作为结果。

所以如果scope1.bundefined

// We start with 
scope1.b && scope1.b.value || 0 
// which is 
undefined && scope1.b.value || 0 
// which is 
undefined || 0 
// which is 
0 

...但如果scope.b就像是一个对象引用一个truthy值:

// We start with 
scope1.b && scope1.b.value || 0 
// which is 
scope1.b.value || 0 
// which is 
scope1.b.value // *IF* scope1.b.value is truthy, or 
0    // If it isn't 

(回想一下, “falsey” 值是undefinednull,0,"",NaN,当然还有false;“truthy”值a重新所有其他)

例:

var scope1; 
 

 
scope1 = {a: "foo"}; 
 
snippet.log(scope1.b && scope1.b.value || 0); // 0 
 

 
scope1 = {a: "foo", b: {}}; 
 
snippet.log(scope1.b && scope1.b.value || 0); // 0 
 

 
scope1 = {a: "foo", b: {value: 42}}; 
 
snippet.log(scope1.b && scope1.b.value || 0); // 42
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


我不推荐它,但你可以一个函数为这个来处理任意深度:

function resolve(obj, path, defValue) { 
 
    var rv = path.split(".").reduce(function(o, p) { 
 
    return o && o[p]; 
 
    }, obj); 
 
    return rv || defValue; 
 
} 
 

 
var scope1; 
 

 
scope1 = {a: "foo"}; 
 
snippet.log(resolve(scope1, "b.value", 0)); // 0 
 

 
scope1 = {a: "foo", b: {}}; 
 
snippet.log(resolve(scope1, "b.value", 0)); // 0 
 

 
scope1 = {a: "foo", b: {value: 42}}; 
 
snippet.log(resolve(scope1, "b.value", 0)); // 42 
 

 
scope1 = {a: "foo", b: {}}; 
 
snippet.log(resolve(scope1, "b.baz.boz.value", 0)); // 0 
 

 
scope1 = {a: "foo", b: {baz: {boz: {value: 67}}}}; 
 
snippet.log(resolve(scope1, "b.baz.boz.value", 0)); // 67
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

即实现不支持括号符号,只是点符号,但你可以自由地写resolve(obj, "foo.0.bar.42", 0)如果你有你需要的数字指标,因为它不符合标准的JavaScript解析规则。 (或者将其扩展到支持[]就不会那么难)。

+0

明白了!这绝对有帮助!所以&&是最好的(或最短的代码),我们可以用JavaScript做对吗? – 2014-12-14 17:38:07

+0

@ChandlerLee:除非你想为它编写一个函数,并且执行'var v1 = foo(scope1,“b.value”,0);',这可能是过量的。 :-)我增加了一个这样做的例子。最后几个例子* *短于'var v1 = scope1.b && scope1.b.baz && scope1.b.baz.boz && scope1.b.baz.boz.value || 0;'会... – 2014-12-14 17:49:35