【问题标题】:How to avoid 'undefined' errors in nested objects [duplicate]如何避免嵌套对象中的“未定义”错误[重复]
【发布时间】:2018-12-02 09:10:25
【问题描述】:

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

下面代码 sn-p 的底部是一个可行的解决方案示例,但不优雅(充其量)。

很高兴看到一些原生 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');
    }
  }
);

【问题讨论】:

  • 为什么不抓住它,然后做任何你想做的事情,而不是对所有事情都使用 if 语句?
  • @chevybow 我的例子可能过于笼统。我写了很多 JSX,所以我经常使用三元运算符。在这种情况下,Try/Catch 不是一个选项,所以我一直在寻找一种功能性方法。
  • 如果console.log(obj?.foo?.bar?.baz) 看起来更优雅,请参阅github.com/tc39/proposal-optional-chaining
  • @Aprillion 这是一个很好的解决方案!我认为第 1 阶段对于我的团队来说太远了,但无法舒适地使用 Babel 插件。你知道函数式方法吗?
  • This 你可能会感兴趣

标签: javascript javascript-objects


【解决方案1】:

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'

【讨论】:

    【解决方案2】:

    不确定这是否足以改进,但您可以使用具有以下条件的单个 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');
      }
    });

    【讨论】:

      【解决方案3】:

      您可以使用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'])));

      【讨论】:

        【解决方案4】:

        只是为了分享我的两分钱:

        前段时间我做了一个函数,允许使用代理安全地访问 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 以供进一步参考。

        【讨论】:

          猜你喜欢
          • 2010-11-14
          • 2016-10-18
          • 2015-07-30
          • 2016-03-12
          • 2020-04-01
          • 1970-01-01
          • 2015-05-23
          • 2012-10-05
          • 2017-02-05
          相关资源
          最近更新 更多