【问题标题】:in javascript, is there syntatic shortcut checking existence of each layer of embedded object?在javascript中,是否有语法快捷方式检查每一层嵌入对象的存在?
【发布时间】:2011-06-10 06:38:18
【问题描述】:

例如下面的代码

如果(obj.attr1.attr2.attr3.attr4 == '常量')返回;

需要改写为

如果(obj.attr1 && obj.attr1.attr2 && obj.attr1.attr2.attr3 && obj.attr1.attr2.attr3.attr4 == 'constant' ) 返回;

每个层都需要单独测试,我是否正确,或者是否有一个语法快捷方式?

如果这是一次性的不会有问题,但这种结构渗透到我的代码中。



从答案来看,这是我现场的解决方案:

尝试{ if( obj.attr1.attr2.attr3.attr4 != 'const' ) throw 'nada'; } 捕捉(e){ nonblockAlert('相关消息'); 返回; };

这是可行的,因为由于 attr 不存在而引发的错误被本地 throw() 捕获。问题是语法不适合普通的 if then else 控件。

【问题讨论】:

  • 这基本上是我所知道的最好的方式。
  • @Mauvis - 你认为有什么方法可以普遍捕获特定错误并让语句通过吗?
  • 总是有window.onerror ;)
  • 只是出于好奇,您的函数期望接收什么样的代码路径,是否有可能真正的数据是(obj 可能为 null?obj.foo 可能为 null?obj.foo。 bar 可能为空?等等)我不了解您,但是当我有这样的数据结构或深层对象时,每个子节点都可能为空的机会很少,并且表明重新设计可能会有所帮助。通常,如果您在一个对象中有一个属性,那么其余的“模式”应该被很好地定义。

标签: javascript object syntax


【解决方案1】:

没有真正的捷径。你可以编写一个辅助函数来为你做这件事,可以浓缩为:

function getProp(obj){
    var i=0, l=arguments.length;
    while(i<l && (obj = obj[arguments[i++]]));
    return obj;
}
if( getProp(obj, 'attr1', 'attr2', 'attr3', 'attr4') == 'constant')

或者你可以这样做:

var tmp;
if((tmp = obj.attr1)
    && (tmp=tmp.attr2)
    && (tmp=tmp.attr3)
    && (tmp.attr4 == 'constant')) {

【讨论】:

  • 谢谢 - 虽然 getProp() 有效,但有点麻烦。认为将与下面的丑陋接球/投掷一起去
  • +1 用于第二个解决方案。很优雅
  • @cc young - 你的代码,你可以做任何事情,但我个人认为定义一次然后有这个 if 语句远比每次都放一个 try/catch 麻烦得多。此外,您的 try 需要包装 整个 if 子句,可能跨越数十行或更多行。
【解决方案2】:

正如人们提到的,但没有人做过,你可以使用 try/catch:

try {
    if(obj.attr1.attr2.attr3.attr4 == 'constant') return;
} catch(e) {}

这不是最好的代码,但它是最简洁且易于阅读的。避免它的最佳方法是不要将可能不存在的对象树嵌套得如此深。

【讨论】:

  • 上面的getProp()和throw这两种方法,我觉得throw比较不麻烦。结合起来可以使语法更好,但是由于不可能推迟对函数 args 的评估,因此只能使用 catch 和 throw。谢谢。
  • 根据上面的评论,你认为有什么方法可以普遍捕捉到这个特定的错误并让语句通过吗?
  • 请注意,如果您必须尝试捕获类似的东西,问题可能出在其他地方?问问自己:“我是否通过试图忽略错误来掩盖真正的问题?”深层嵌套对象很可能是垃圾,真的是这样吗?如果是这样,可能需要验证功能。
【解决方案3】:

有趣的问题 - 虽然我自己从来没有遇到过这个问题。我能想到的最好的选择是编写一个辅助函数:

function get(chain, context) {
   var o = arguments.length == 2 ? context : window,
       c = chain.split('.');
   for (var i = 0; i < c.length; i++) {
       if (!o) return null;
       o = o[c[i]];
   }
   return o;
}

如果obj 是全局的,那么您可以执行以下操作:

if (get('obj.attr1.attr2.attr3.attr4') == 'constant') return;

否则:

if (get('attr1.attr2.attr3.attr4', obj) == 'constant') return;

【讨论】:

    【解决方案4】:

    不,很遗憾,没有,除了使用try/catch。不过,您可以为自己编写一个辅助函数(未经测试,但概念已经存在):

    function existsAndEquals(obj, layers, compare) {
    
        for (var i = 0; i < layers.length; i++)
            if (!(obj = obj[layers[i]]))
                return false;
    
        return obj == compare;
    
    }
    
    if (existsAndEquals(obj, ['attr1', 'attr2', 'attr3', 'attr4'], 'constant'))
        // ...
    

    【讨论】:

      【解决方案5】:

      您可以使用调用(或应用)来转移字符串评估的上下文 从窗口到任何物体

      function getThis(string){
          var N= string.split('.'), O= this[N.shift()];
          while(O && N.length) O= O[N.shift()];
          return O;
      }
      
      
      window.obj={
          attr1:{
              attr2:{
                  attr3:{
                      attr4: 'constant!'
                  }
              }
          }
      }
      

      getThis('obj.attr1.attr2.attr3.attr4');

      /* 返回值:(String) 'constant!' */

      getThis.call(obj, 'attr1.attr2.attr3.attr4');

      /* 返回值:(String) 'constant!' */

      【讨论】:

        猜你喜欢
        • 2017-06-05
        • 2020-01-14
        • 2011-02-20
        • 2014-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-05
        相关资源
        最近更新 更多