JS检查深层对象属性是否存在

9

我正在尝试找到一种优雅的方式来检查对象中是否存在某些深层属性。因此,实际上是试图避免对未定义变量进行冗长的保护性检查。

if ((typeof error !== 'undefined') && 
  (typeof error.responseJSON !== 'undefined') &&
  (typeof error.responseJSON.error) && 
  (typeof error.responseJSON.error.message)) {
      errorMessage = error.responseJSON.error.message;
}

我正在考虑的是一个类似便捷功能的东西。
if (exists(error.responseJSON.error.message)) { ... }

任何想法?为了方便起见,使用underscore库来解决问题是可以的。

你可以通过将请求作为字符串传递给函数来实现这一点。该函数应该通过“.”或其他方式拆分字符串,然后迭代每个段以查找每个值。不过,关于此问题还有其他问题和好的答案:https://dev59.com/Gmoy5IYBdhLWcg3wCpoz - Olical
我在思考是否有一种处理对象而不是字符串的方法?当然,我可以只是将对象JSON.stringify,但如果它可以直接处理对象,我会感觉更好。 - Marcus
1
如果您使用对象,您需要创建整个结构(这很笨重,甚至比到处使用 && 更糟)。字符串可能看起来很奇怪,但它是最灵活和紧凑的解决方案。另一种选择是传递一个数组,它只是预先拆分的字符串。然后迭代该数组并深入目标对象。 - Olical
2个回答

21

有几种可能性:

尝试捕获

try {
  errorMessage = error.responseJSON.error.message;
} catch(e) { /* ignore the error */}

失败于:

Object.defineProperty(error, 'responseJSON', {
  get: function() { throw new Error('This will not be shown')
});

&&

errorMessage = error && error.responseJSON && error.responseJSON.error && error.responseJSON.error.message;

失败原因:

error.responseJSON = 0;
// errorMessage === 0 instead of undefined

函数

function getDeepProperty(obj,propstr) {
  var prop = propstr.split('.');
  for (var i=0; i<prop.length; i++) {
    if (typeof obj === 'object')
      obj = obj[prop[i]];
  }
  return obj;
}

errorMessage = getDeepProperty(error, 'responseJSON.error.message');

// you could put it all in a string, if the object is defined in the window scope

失败原因:

// It's hard(er) to use

替代函数 - 请查看@Olical的评论

function getDeepProperty(obj) {
  for (var i=1; i<arguments.length; i++) {
    if (typeof obj === 'object')
      obj = obj[arguments[i]];
  }
  return obj;
}

errorMessage = getDeepProperty(error, 'responseJSON', 'error', 'message');

6

尝试使用这个underscore mixin来查找一个带路径的变量。它接受一个对象和字符串,且可以快速地查找需要的变量。

_.mixin({
    lookup: function (obj, key) {
        var type = typeof key;
        if (type == 'string' || type == "number") 
            key = ("" + key).replace(/\[(.*?)\]/, function (m, key) { //handle case where [1] may occur
                return '.' + key.replace(/["']/g, ""); //strip quotes
            }).split('.');
        for (var i = 0, l = key.length; i < l; i++) {
            if (_.has(obj, key[i])) 
                obj = obj[key[i]];
            else 
                return undefined;
            }
        return obj;
    }
});

现在按照您的示例进行调用:
_.lookup(error, 'responseJSON.error.message') // returns responseJSON.error.message if it exists otherwise `undefined`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接