在JavaScript中,是否有更简单的方法来检查属性的属性是否存在?

在JavaScript中,是否有更简单的方法来检查属性的属性是否存在?,javascript,Javascript,有没有一种简单的方法可以本机确定JavaScript中的对象中是否存在deep属性?例如,我需要访问如下属性: var myVal = appData.foo.bar.setting; def myVal = appData?.foo?.bar?.setting 但有可能foo、foo.bar或foo.bar.setting尚未定义。在Groovy中,我们可以执行以下操作: var myVal = appData.foo.bar.setting; def myVal = appData?.

有没有一种简单的方法可以本机确定JavaScript中的对象中是否存在deep属性?例如,我需要访问如下属性:

var myVal = appData.foo.bar.setting;
def myVal = appData?.foo?.bar?.setting
但有可能foo、foo.bar或foo.bar.setting尚未定义。在Groovy中,我们可以执行以下操作:

var myVal = appData.foo.bar.setting;
def myVal = appData?.foo?.bar?.setting

在JavaScript中是否有类似的方法来实现这一点,而不必编写自定义函数或嵌套的if语句?我发现它很有用,但我希望有一种更优雅、更少定制的方式。

我觉得这很方便:

var myVal = (myVal=appData) && (myVal=myVal.foo) && (myVal=myVal.bar) && myVal.settings;
如果属性存在,将尝试序列的下一部分

&&
之前的表达式计算结果为false时,将不检查表达式的下一部分。如果未定义任何
myVal.appData.foo.bar.settings
,则
myVal
undefined
)的值将计算为
false

,您可以尝试此操作

var x = {y:{z:{a:'b'}}}
x && x.y && x.y.z && x.y.z.a //returns 'b'
这不如groovy表达式好,但它可以工作。遇到第一个未定义的变量后,计算将停止。

如果,在:

var myVal = appData.foo && appData.foo.bar && appData.foo.bar.setting;
myVal
不是未定义的

var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.setting;
另一种选择:

try {
    var myVal = appData.foo.bar.setting;
} catch (e) {
    var myVal = undefined;
}

.operator实际上并不用于访问这样的对象。可能使用函数会是一个好主意。

我只是捏造了这个,所以它可能无法完全正常工作,我还包括了两个测试用例

function hasPropertyChain(o, properties) {

    var i = 0,
        currentPropertyChain = o;

    if(!o) {
        return false;
    }

    while(currentPropertyChain = currentPropertyChain[properties[i++]]);

    return i - 1 === properties.length;
}


alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c'])); // true
alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c', 'd'])); // false

我发现其他方法有点大。那么,以下方法的主要缺点是什么:

// Pass the path as a string, parse it, and try to traverse the chain.
Object.prototype.pathExists = function(path) {
    var members = path.split(".");
    var currentMember = this;

    for (var i = 0; i < members.length; i++) {
        // Here we need to take special care of possible method 
        // calls and arrays, but I am too lazy to write it down.
        if (currentMember.hasOwnProperty(members[i])) {
            currentMember = currentMember[members[i]];   
        } else {
            return false;
        }
    }
    return true;
}
//将路径作为字符串传递,对其进行解析,然后尝试遍历该链。
Object.prototype.pathExists=函数(路径){
var members=path.split(“.”);
var currentMember=此;
对于(var i=0;i
基本上,我们在对象上定义一个方法(不一定),该方法获取嵌套对象的路径并返回存在确认,如
appData.pathExists(“foo.bar.setting”);

编辑:
检查
对象[prop]==undefined
在语义上是不正确的,因为即使定义了属性,它也会返回false,尽管它的值是undefined
;这就是为什么我使用
hasOwnProperty
检查属性是否已定义。如果只需要获取值,这可能并不重要。

除了遵守Demeter定律之外,不。我多么希望在C#中有这个运算符……请注意,这种方法对于深度嵌套的变量非常有用。当变量由两个名称组成时,例如
foo.bar
myVal=foo&&foo.bar
更方便。没有理由进行这些“子赋值”在括号内。JavaScript返回序列的最后一个表达式的实际值,或者
false
。它不会像其他具有类似短路运算符的语言一样强制将值设置为布尔值。@Pointy:子赋值是为了避免重复属性名,以便总代码长度为O(N)而不是O(N^2)。我自己会尝试在长度开始重要时切换到自定义函数。@Pointy
var myVal=appData&&foo&&bar&&settings
不会产生所需的结果。请参阅我以前的注释。否,但我认为Pointy的意思是:
var myVal=appData&&appData.foo&&appData.foo.bar&&appData.foo.bar.settings。如果变量名不长,实际上我更喜欢这种方式。但是如果它们长,我更喜欢你的方式,Rob。无论哪种方式,我都喜欢。+1