开发者

in javascript, is there syntatic shortcut checking existence of each layer of embedded object?

for example, the following code

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

needs to be rewritten as

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

am I correct in that each layer needs to be tested individually, or is there a syntactic shortcut for this?

if this were a one-shot would not be a problem, but this construct permeates my code.



from answers, here is the solution I have in situ:

开发者_Go百科try{ if( obj.attr1.attr2.attr3.attr4 != 'const' ) throw 'nada'; } catch(e){
    nonblockAlert( 'Relevant Message' );
    return;
};

this works since the error thrown for attr's non-existence is caught with the local throw(). the problem is the syntax does not fit in will with a normal if then else control.


there's no real shortcut. You can write a helper function to do it for you, something that can condense to:

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')

or you can do:

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


As people have mentioned, but nobody has done, you can use try/catch:

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

It's not the best code ever, but it's the most concise, and easily readable. The best way of avoiding it would be not to have so deeply nested a tree of possibly-absent objects.


Interesting question - though I've never had the problem myself. The best alternative I can think of is to write a helper function:

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;
}

If obj is global then you can do something like:

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

Otherwise:

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


No, unfortunately, there isn't, short of using try/catch. You could, though, write yourself a helper function (untested, but the concept is there):

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'))
    // ...


You can use call (or apply) to shift the context of a string evaluation from the window to any object

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');

/* returned value: (String) 'constant!' */

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

/* returned value: (String) 'constant!' */

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜