如果我有对象的引用:
var test = {};
可能(但不是立即)具有嵌套对象,例如:
{level1: {level2: {level3: "level3"}}};
检查深度嵌套对象中是否存在属性的最佳方法是什么?
警报(测试级别1);生成未定义,但警告(test.level1.level2.level3);失败。
我目前正在做这样的事情:
if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
alert(test.level1.level2.level3);
}
但我想知道是否有更好的方法。
我认为下面的脚本提供了更可读的表示。
声明函数:
var o = function(obj) { return obj || {};};
然后这样使用:
if (o(o(o(o(test).level1).level2).level3)
{
}
我称之为“悲伤小丑技巧”,因为它使用了符号o(
编辑:
这是TypeScript的版本
它在编译时提供类型检查(如果使用像Visual Studio这样的工具,还提供智能感知)
export function o<T>(someObject: T, defaultValue: T = {} as T) : T {
if (typeof someObject === 'undefined' || someObject === null)
return defaultValue;
else
return someObject;
}
用法相同:
o(o(o(o(test).level1).level2).level3
但这次intelligense奏效了!
此外,您可以设置默认值:
o(o(o(o(o(test).level1).level2).level3, "none")
另一个版本:
function nestedPropertyExists(obj, props) {
var prop = props.shift();
return prop === undefined
? true
: obj.hasOwnProperty(prop) ? nestedPropertyExists(obj[prop], props) : false;
}
nestedPropertyExists({a:{b:{c:1}}}, ['a','b','c']); // returns true
nestedPropertyExists({a:{b:{c:1}}}, ['a','b','c','d']); // returns false
我知道这个问题很古老,但我想通过将其添加到所有对象来提供一个扩展。我知道人们倾向于不赞成使用Object原型来实现扩展的对象功能,但我发现没有什么比这更容易的了。此外,现在还允许使用Object.defineProperty方法。
Object.defineProperty( Object.prototype, "has", { value: function( needle ) {
var obj = this;
var needles = needle.split( "." );
for( var i = 0; i<needles.length; i++ ) {
if( !obj.hasOwnProperty(needles[i])) {
return false;
}
obj = obj[needles[i]];
}
return true;
}});
现在,为了测试任何对象中的任何属性,只需执行以下操作:
if( obj.has("some.deep.nested.object.somewhere") )
这里有一个jsfiddle来测试它,特别是它包含一些jQuery,如果您直接修改Object.prototype,因为属性变为可枚举,则会中断。这对于第三方图书馆来说应该很好。
另一种解决方法是,例如,使用以下对象:
var x = {
a: {
b: 3
}
};
然后,我所做的是向这个对象添加以下函数:
x.getKey = function(k){
var r ;
try {
r = eval('typeof this.'+k+' !== "undefined"');
}catch(e){
r = false;
}
if(r !== false){
return eval('this.'+k);
}else{
console.error('Missing key: \''+k+'\'');
return '';
}
};
然后您可以测试:
x.getKey('a.b');
如果未定义,则函数返回“”(空字符串),否则返回现有值。
还请考虑检查链接的另一个更复杂的解决方案:JS对象具有属性深度检查
Object.prototype.hasOwnNestedProperty = function(propertyPath){
if(!propertyPath)
return false;
var properties = propertyPath.split('.');
var obj = this;
for (var i = 0; i < properties.length; i++) {
var prop = properties[i];
if(!obj || !obj.hasOwnProperty(prop)){
return false;
} else {
obj = obj[prop];
}
}
return true;
};
// Usage:
var obj = {
innerObject:{
deepObject:{
value:'Here am I'
}
}
}
obj.hasOwnNestedProperty('innerObject.deepObject.value');
注:还有一个递归版本。