【问题标题】:JS: How to return 'undefined' instead of throwing error 'cannot read property x of undefined'JS:如何返回“未定义”而不是抛出错误“无法读取未定义的属性 x”
【发布时间】:2012-06-07 17:05:36
【问题描述】:

当父属性不存在时,让 js 返回 undefined 而不是抛出错误的最佳方法是什么?

例子

a = {}
b = a.x.y.z
// Error: Cannot read property 'value' of undefined
// Target result: b = undefined

【问题讨论】:

  • 如果你不想用大量的try/catch 填充你的代码(这在某种程度上是一个解决方案),在 JS 中通常你在使用之前检查一个对象是否被定义它的特定属性/方法。这意味着,在这种情况下,您应该在访问之前验证a 是否具有x,等等。如果您使用这种方法来模拟命名空间,您可以创建自己的函数,为您递归地执行此操作。

标签: javascript


【解决方案1】:

您必须检查每个属性是否存在:

var b;
if (a.x && a.x.y && a.x.y.z) {
    b = a.x.y.z
}

或者,类似于另一张海报的“safeGet”功能:

var get = function (obj, ns) {
    var y = ns.split('.');
    for(var i = 0; i < y.length; i += 1) {
        if (obj[y[i]]) {
            obj = obj[y[i]];
        } else {
            return;
        }
    }
    return obj;
};

用途:

var b = get(a, 'x.y.z');

【讨论】:

  • 我通常这样做,除了有大量属性(我无法控制,它从其他地方获取数据结构)并且想要一种更短/更简洁的方法
  • 你觉得我的其他建议怎么样?
  • 是的;这是一种 hack,但您可以将其称为:get(someVar, 'x.y.0.z')
  • 这仍然会爆炸,您需要使用 typeof 运算符。
  • @jbabey 你能举一个“爆炸”的例子吗?
【解决方案2】:
try {
  a = {}
  b = a.x.y.z
}
catch (e) {
  b = void 0;
}

【讨论】:

  • @arcyqwerty 我想你可以做到if ( e instanceof TypeError )
  • 是的。假设它工作得很好。如果为 false,则向其添加 throw e
【解决方案3】:

我会稍微冗长:

var b = ((a.x || {}).y || {}).z

【讨论】:

    【解决方案4】:

    您可以编写一个safeGet 辅助函数,例如:

    按照 arcyqwerty 在 cmets 中的建议进行了深入编辑

    var getter = function (collection, key) {
        if (collection.hasOwnProperty(key)) {
            return collection[key];
        } else {
            return undefined;
        }
    };
    
    var drillDown = function (keys, currentIndex, collection) {
        var max = keys.length - 1;
        var key = keys[currentIndex];
    
        if (typeof collection === 'undefined') {
            return undefined;   
        }
    
        if (currentIndex === max) {
            return getter(collection, key);
        } else {
            return drillDown(keys, currentIndex + 1,
                             getter(collection, key));
        }
    };
    
    var safeGet = function (collection, key) {
        if (key.indexOf(".") !== -1) {
            return drillDown(key.split("."), 0, collection);
        } else {
            return getter(collection, key);
        }
    };
    
    a = { x: 1 };
    b = safeGet(a, 'x.y.z');
    

    http://jsfiddle.net/YqdWH/2/

    【讨论】:

    • 需要为许多嵌套键工作,多次调用 safeget 可能会有点长
    • @arcyqwerty 可以通过将密钥解析为由. 分隔的部分并递归调用 safeGet 来轻松处理
    猜你喜欢
    • 1970-01-01
    • 2017-07-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    相关资源
    最近更新 更多