如果我有对象的引用:

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

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


当前回答

我已经使用这个函数来访问深度嵌套对象的财产,它对我来说很有效。。。

这是函数

/**
 * get property of object
 * @param obj object
 * @param path e.g user.name
 */
getProperty(obj, path, defaultValue = '-') {
  const value = path.split('.').reduce((o, p) => o && o[p], obj);

  return value ? value : defaultValue;
}

这是我访问深度嵌套对象属性的方式

{{ getProperty(object, 'passengerDetails.data.driverInfo.currentVehicle.vehicleType') }}

其他回答

这个功能怎么样?它不需要单独列出每个嵌套属性,而是保持“dot”语法(尽管是字符串),使其更具可读性。如果未找到属性,则返回undefined或指定的默认值,如果找到,则返回属性的值。

val(obj, element, default_value)
    // Recursively checks whether a property of an object exists. Supports multiple-level nested properties separated with '.' characters.
    // obj = the object to test
    // element = (string or array) the name of the element to test for.  To test for a multi-level nested property, separate properties with '.' characters or pass as array)
    // default_value = optional default value to return if the item is not found. Returns undefined if no default_value is specified.
    // Returns the element if it exists, or undefined or optional default_value if not found.
    // Examples: val(obj1, 'prop1.subprop1.subsubprop2');
    // val(obj2, 'p.r.o.p', 'default_value');
    {

        // If no element is being requested, return obj. (ends recursion - exists)
        if (!element || element.length == 0) { return obj; }

        // if the element isn't an object, then it can't have properties. (ends recursion - does not exist)
        if (typeof obj != 'object') { return default_value; }

        // Convert element to array.
        if (typeof element == 'string') { element = element.split('.') };   // Split on dot (.)

        // Recurse into the list of nested properties:
        let first = element.shift();
        return val(obj[first], element, default_value);

    }

我以以下方式使用函数。

var a = {};
a.b = {};
a.b.c = {};
a.b.c.d = "abcdabcd";

function isDefined(objectChainString) {
    try {
        var properties = objectChainString.split('.');
        var currentLevel = properties[0];
        if (currentLevel in window) {
            var consolidatedLevel = window[currentLevel];
            for (var i in properties) {
                if (i == 0) {
                    continue;
                } else {
                    consolidatedLevel = consolidatedLevel[properties[i]];
                }
            }
            if (typeof consolidatedLevel != 'undefined') {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } catch (e) {
        return false;
    }
}

// defined
console.log(checkUndefined("a.b.x.d"));
//undefined
console.log(checkUndefined("a.b.c.x"));
console.log(checkUndefined("a.b.x.d"));
console.log(checkUndefined("x.b.c.d"));

根据之前的评论,这里是另一个无法定义主对象的版本:

// Supposing that our property is at first.second.third.property:
var property = (((typeof first !== 'undefined' ? first : {}).second || {}).third || {}).property;

对该答案进行轻微编辑,以允许在路径中嵌套数组

var has=函数(obj,key){return key.split(“.”).every(函数(x){if(类型obj!=“对象”| | obj===空| |!x在obj中)return false;if(obj.constructor==数组)obj=obj[0];obj=obj[x];返回true;});}

检查链接答案的用法:)

您可以使用“.”分隔对象和路径

函数checkPathExist(obj,路径){var pathArray=路径.split(“.”)for(pathArray的var i){if(反射get(obj,i)){obj=obj[i];}其他{return false;}}返回true;}var测试={level1:{level2:{level3:‘level3‘}}}};console.log('level.level.level3=>',checkPathExist(测试,'level.level 2.level3'));//真的console.log('level.level.foo=>',checkPathExist(测试,'level.level 2.foo'));//假的