我正在尝试访问像这样的对象属性:
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
明显的||经营者没有给我我想要的东西。我知道我可以做以下事情
var vv2 = (scope1 && scope1.b ? scope1.b.value : 0);
但这会使代码变得非常冗长......所以任何人都知道有没有更简单的方法来做我想做的事情?感谢。
答案 0 :(得分:4)
通常的答案是&&
运算符:
var v1 = scope1.b && scope1.b.value || 0;
...因为与||
一样,&&
是curiously powerful:&&
评估左侧操作数,如果它是假的,则采用该假名价值作为结果;如果左侧操作数值为真,则&&
计算右侧操作数并将该值作为结果。
如果scope1.b
是undefined
:
// 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
是像对象引用那样的真值:
// 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"值为undefined
,null
,0
,""
,NaN
,当然,false
;以及" truthy"值都是其他值。)
示例:
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>
&#13;
我不推荐它,但你可以编写一个处理任意深度的函数:
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
&#13;
<!-- 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>
&#13;
该实现不支持括号表示法,只是点符号,但如果您有所需的数字索引,则可以自由编写resolve(obj, "foo.0.bar.42", 0)
,因为它不受标准JavaScript解析规则的约束。 (或者将其扩展到支持[]
并不会那么难。)