如何避免嵌套对象中的“未定义”错误

时间:2018-06-22 21:04:15

标签: javascript javascript-objects

我正在寻找一些好的策略,以避免在使用点表示法在可能存在或不存在的对象中调用子代的子代时避免JavaScript中的错误。

下面的代码段底部是一个可行的解决方案示例,但效果不佳(充其量)。

很高兴看到一些本机JavaScript解决方案,甚至可以帮助避免此类错误的外部库。

const object1 = {
  foo: {
    bar: {
      baz: 'payload'
    }
  }
};


const object2 = {};

const array = [object1, object2];

// this will fail on object2 because obj.foo is undefined
array.forEach(obj => {
    if (obj.foo.bar.baz) {
      console.log(obj.foo.bar.baz);
     } else {
      console.log('undefined');
     }
  } 
);

// this will work, but it's horrible to write all those nested if statements.
array.forEach(obj => {
    if (obj) {
      if (obj.foo) {
        if (obj.foo.bar) {
          if (obj.foo.bar.baz) {
          console.log(obj.foo.bar.baz);
          }
        }
      }
    } else {
      console.log('undefinded');
    }
  }
);

4 个答案:

答案 0 :(得分:7)

Lodash已经为我们做到了:https://lodash.com/docs#get

const object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3

_.get(object, ['a', '0', 'b', 'c']);
// => 3

_.get(object, 'a.b.c', 'default');
// => 'default'

答案 1 :(得分:4)

不确定这是否足以改进,但是可以使用具有以下条件的单个if语句:

(obj && obj.foo && obj.foo.bar && obj.foo.bar.baz)

这将检查obj.foo.bar.baz是否存在。

const array=[{foo:{bar:{baz:'payload'}}},{}]

array.forEach(obj => {
  if (obj && obj.foo && obj.foo.bar && obj.foo.bar.baz) {
    console.log(obj.foo.bar.baz);
  } else {
    console.log('undefined');
  }
});

答案 2 :(得分:4)

您可以将所有支票与logical AND &&链接。

const
    object1 = { foo: { bar: { baz: 'payload' } } },
    object2 = {},
    array = [object1, object2];

array.forEach(obj => {
    if (obj && obj.foo && obj.foo.bar && obj.foo.bar.baz) {
        console.log(obj.foo.bar.baz);
    } else {
        console.log('undefined');
    }
});

要进行自动检查,您可以获取一组键并返回值或undefined

const
    getValue = (object, keys) => keys.reduce((o, k) => (o || {})[k], object),
    object1 = { foo: { bar: { baz: 'payload' } } },
    object2 = {},
    array = [object1, object2];

array.forEach(obj => console.log(getValue(obj, ['foo', 'bar', 'baz'])));

答案 3 :(得分:0)

只分享我的两分钱:

前一段时间,我做了一个函数,该函数可以使用代理安全地访问javascript中的深层属性:

// Here is where the magic happens
function optional(obj, evalFunc, def) {

  // Our proxy handler
  const handler = {
    // Intercept all property access
    get: function(target, prop, receiver) {
      const res = Reflect.get(...arguments);

      // If our response is an object then wrap it in a proxy else just return
      return typeof res === "object" ? proxify(res) : res != null ? res : def;
    }
  };

  const proxify = target => {
    return new Proxy(target, handler);
  };

  // Call function with our proxified object
  return evalFunc(proxify(obj, handler));
}

const obj = {
  items: [{
    hello: "Hello"
  }]
};

console.log(optional(obj, target => target.items[0].hello, "def")); // => Hello
console.log(optional(obj, target => target.items[0].hell, {
  a: 1
})); // => { a: 1 }

此外,我为此写了article,以供进一步参考。