在Javascript中将嵌套对象测试为未定义[重复]

Posted

技术标签:

【中文标题】在Javascript中将嵌套对象测试为未定义[重复]【英文标题】:Testing nested objects as undefined in Javascript [duplicate] 【发布时间】:2012-06-10 17:18:17 【问题描述】:

可能重复:javascript test for existence of nested object key

我试图通过测试某个对象是否不是 undefined 来为formset 构造错误消息,如果它不是undefined,那么我最终会填充它带有该错误消息。主要问题是我必须验证每个嵌套对象是否为undefined,这会导致一些非常丑陋的代码。示例如下:

errorsForField: function(fieldName, formsetName, formNumber) 
            if (typeof this.model.errors != 'undefined')

                var fieldError = document.createElement('span');
                $(fieldError).addClass('field-error');

                // THE FOLLOWING LINE THROWS ERROR.
                if (formsetName && _.isUndefined(this.model.errors[formsetName][fieldName]) != true) 
                    $(fieldError).text(this.model.errors[formsetname][fieldName]);
                 else if (typeof this.model.errors[fieldName] != "undefined")
                    $(fieldError).text(this.model.errors[fieldName]);
                

                this.errors[fieldName] = fieldError.outerhtml;
                return fieldError.outerHTML; 
            
            return false; 
        ,

我收到一条错误消息,指出我无法确定 undefined object[fieldName] this.model.errors[formsetName]。换句话说,我必须首先确定this.model.errors[formsetName] 是否为空,然后然后 测试[fieldname] 是否为undefined

这似乎是一个非常麻烦的解决方案。有什么改变这个的建议吗?

【问题讨论】:

我从未在纯 JavaScript 中看到过解决此问题的方法。顺便说一下,这被称为“安全导航”或“吸收空值”。归结为 JS 的 Coffeescript 就有这个功能。您可能想查看它们的实现以获取灵感;它似乎使用了很多三元运算符。 overview of Coffeescript 有一个例子。在该页面上搜索“吸收空值” 【参考方案1】:

您可以创建一个库函数,将属性名称作为参数,如果存在则返回最终值,否则返回 null:

function TryGetPropertyValue(o, propertyName1 /*, ... propertyNameN */) 
    var names = [].slice.call(arguments, 1);
    while (o && names.length) 
        o = o[names.shift()];
    
    return names.length ? null : o;

这样称呼:

var err = TryGetPropertyValue(this.model.errors, formsetName, fieldName) ||
          TryGetPropertyValue(this.model.errors, fieldName);
if (err != null) 
    $(fieldError).text(err);

如果你希望它返回undefined而不是null,如果没有找到该字段,你可以稍微改变一下函数:

function TryGetPropertyValue(o, propertyName1 /*, ... propertyNameN */) 
    var names = [].slice.call(arguments, 1);
    while (o && names.length) 
        o = o[names.shift()];
    
    if (names.length == 0) 
        return o;
    

http://jsfiddle.net/HbggQ/

【讨论】:

是否可以通过仅传递属性名称(而不是通过路径)来获取属性值。例如,通过传递 'isValid' 属性名称,它应该得到所有出现的 'isValid' @Narendra - 您可以编写一个遍历对象查找属性的函数,但如果对象包含循环引用或对window 的引用,您很快就会遇到麻烦。 【参考方案2】:

正如 Paul 所建议的,这是 Javascript 的固有限制。即使是 Coffeescript(它只是 JS 之上的一层语法糖)也不能真正解决这个问题。它只是将解决方法隐藏在它的语法糖下(诚然这真的很方便)

如果你想坚持使用 Javascript,你基本上有两个选择:使用三元运算符,或者使用布尔运算符。以下是每个检查 A.B.C.D 的示例(其中 A、B、C 或 D 可能不存在):

// Returns A.B.C.D, if it exists; otherwise returns false (via ternary)
return !A ? false :
            !A.B ? false :
                   !A.B.C ? false :
                            A.B.C.D ? A.B.C.D : false;

// Returns A.B.C.D, if it exists; otherwise returns false (via booleans)
return A && A.B && A.B.C && A.B.C.D;

显然后者要短得多。这两种解决方案都依赖于 Javascript 的“真实性”(即值 0""nullundefined 算作假)。这对您的情况应该没问题,因为这些值都没有错误属性。但是,如果您确实需要区分(例如)0undefined,则可以使用三元样式,并将!A 替换为typeof(A) == 'undefined'

【讨论】:

以上是关于在Javascript中将嵌套对象测试为未定义[重复]的主要内容,如果未能解决你的问题,请参考以下文章

切换嵌套JavaScript对象的值[关闭]

如何在javascript中将嵌套对象转换为对象数组? [关闭]

Mongoose/MongoDB 结果字段在 Javascript 中显示为未定义

Mongoose/MongoDB 结果字段在 Javascript 中显示为未定义

在Javascript中将数组转换为嵌套的JSON?

由于某些 javascript 提升,变量显示为未定义