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

Posted

技术标签:

【中文标题】在 JavaScript 中,是不是有更简单的方法来检查属性的属性是不是存在?【英文标题】:In JavaScript, is there an easier way to check if a property of a property exists?在 JavaScript 中,是否有更简单的方法来检查属性的属性是否存在? 【发布时间】:2011-10-03 15:01:17 【问题描述】:

有没有一种简单的方法来原生地确定 javascript 中的对象中是否存在深层属性?例如,我需要访问这样的属性:

var myVal = appData.foo.bar.setting;

但有可能 foo、foo.bar 或 foo.bar.setting 尚未定义。在 Groovy 中,我们可以这样做:

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

在 JavaScript 中是否有类似的方法可以做到这一点,而无需编写自定义函数或嵌套 if 语句?我发现this answer 很有用,但希望有一种更优雅、更少自定义的方式。

【问题讨论】:

遵守得墨忒耳法则之外,没有。 我多么希望我们在 C# 中有那个运算符... v8.dev/features/optional-chaining 【参考方案1】:

我觉得这很方便:

var myVal = (myVal=appData) && (myVal=myVal.foo) && (myVal=myVal.bar) && myVal.settings;

如果存在属性,将尝试序列的下一部分。

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

【讨论】:

请注意,这种方法对于深度嵌套的变量非常有用。当变量由两个名字组成时,如foo.barmyVal = foo && foo.bar更方便。 括号内的那些“子任务”没有理由。 JavaScript 返回序列最后一个表达式的实际值,否则返回false。它不会像其他具有类似短路运算符的语言那样将值强制为布尔值。 @Pointy:子分配是为了避免重复属性名称,以便整体代码长度为 O(N) 而不是 O(N^2)。我自己会尝试在长度开始重要时切换到自定义函数。 @Pointy var myVal = appData && foo && bar && settings 不会产生预期的结果。请参阅我之前的评论。 不,但我认为尖的意思是:var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.settings;。如果 var 名称不长,实际上我更喜欢这种方式。但如果它们很长,我更喜欢你的方式,Rob。不管怎样,我喜欢它。 +1【参考方案2】:

抱歉,不太好:

var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.setting;

另一种选择:

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

.运算符并不是真正用于访问这样的对象。可能使用函数是个好主意。

【讨论】:

【参考方案3】:

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

// 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;

基本上,我们在对象上定义一个方法(不一定),该方法获取嵌套对象的路径并返回存在确认,如appData.pathExists("foo.bar.setting");

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

【讨论】:

【参考方案4】:

如果,之后:

var myVal = appData.foo && appData.foo.bar && appData.foo.bar.setting;

myVal 不是undefined,它将保存appData.foo.bar.setting 的值。

【讨论】:

【参考方案5】:

你可以试试这个

var x = y:z:a:'b'
x && x.y && x.y.z && x.y.z.a //returns 'b'

这不如 groovy 表达式好,但它有效。遇到第一个未定义的变量后,评估停止。

【讨论】:

【参考方案6】:
var product = ...,
    offering = (product||).offering,
    merchant = (offering||).merchant,
    merchantName = (merchant||).name;
if (merchantName)
   displayMerchantName(merchantName);

http://osteele.com/archives/2007/12/cheap-monads

【讨论】:

【参考方案7】:

我刚刚做了这个,所以它可能无法完全正确地工作,我还包含了两个测试用例。

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

【讨论】:

以上是关于在 JavaScript 中,是不是有更简单的方法来检查属性的属性是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET 核心中创建 JWT 是不是有更简单的方法?又名“JWT 身份验证的最佳实践?”

我们在 JavaScript 中有更简单的三元运算符吗? [复制]

是否有更简单的方法在 Roblox (Lua) 上的父对象中查找对象

检查元素是不是是javascript中的对象[重复]

Oracle SQL - 是不是有更有效的方法来组织大量案例语句

给定文件系统路径,是不是有更短的方法来提取没有扩展名的文件名?