如果我有对象的引用:

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);
}

但我想知道是否有更好的方法。


当前回答

在typeScript中,您可以执行以下操作:

 if (object.prop1 && object.prop1.prop2 && object.prop1.prop2.prop3) {
    const items = object.prop1.prop2.prop3
    console.log(items);
 }

其他回答

function propsExists(arg) {
  try {
    const result = arg()
  
    if (typeof result !== 'undefined') {
      return true
    }

    return false
  } catch (e) {
    return false;
  }
}

此函数还将测试0,null。如果他们在场,它也将返回真实。

例子:

函数propsExists(arg){尝试{常量结果=arg()if(结果类型!==“undefined”){返回true}return false}捕获(e){return false;}}让obj={测试:{a: 空,b: 0,c: 未定义,d: 4中,e: “嘿”,f: ()=>{},g: 5.4中,h: 假,i: 真的,j: {},k: [],我:{a: 1中,}}};console.log('obj.test.a',propsExists(()=>obj.test/a))console.log('obj.test.b',propsExists(()=>obj.test.b))console.log('obj.test.c',propsExists(()=>obj.test.c))console.log('obj.test.d',propsExists(()=>obj.test-d))console.log('obj.test.e',propsExists(()=>obj.test.ex))console.log('obj.test.f',propsExists(()=>obj.test-f))console.log('obj.test.g',propsExists(()=>obj.test/g))console.log('obj.test.h',propsExists(()=>obj.test.h))console.log('obj.test.i',propsExists(()=>obj.test-i))console.log('obj.test.j',propsExists(()=>obj.test.j))console.log('obj.test.k',propsExists(()=>obj.test.k))console.log('obj.test.l',propsExists(()=>obj.test/l))

我认为下面的脚本提供了更可读的表示。

声明函数:

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")

这是我从奥利弗·斯蒂尔那里学到的一个模式:

var level3 = (((test || {}).level1 || {}).level2 || {}).level3;
alert( level3 );

事实上,整篇文章讨论了如何在javascript中实现这一点。他决定使用上面的语法(一旦你习惯了,它就不那么难读了)作为成语。

另一种解决方法是,例如,使用以下对象:

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');

注:还有一个递归版本。

CMS解决方案工作得很好,但使用/语法可能更方便。我建议如下

var checkNested = function(obj, structure) {

  var args = structure.split(".");

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
};

您可以简单地使用使用点的对象表示法,而不是提供多个参数

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1.level2.level3'); // true
checkNested(test, 'level1.level2.foo'); // false