2016-12-05 48 views
0

我有許多子屬性和對象在Javascript中的對象。JavaScript斷言對象鏈

所以我的一些代碼行是這樣的:

obj.eventOfType = (el.openSocial && el.openSocial.embed && el.openSocial.embed.context && 
        el.openSocial.embed.context.openSocial && el.openSocial.embed.context.openSocial.connections && 
        el.openSocial.embed.context.openSocial.connections.generator && el.openSocial.embed.context.openSocial.connections.generator.displayName) ? 
       el.openSocial.embed.context.openSocial.connections.generator && el.openSocial.embed.context.openSocial.connections.generator.displayName || ""; 

不很好看。於是我想到了一個函數,寫了這個:在#1所以

/** 
    * assert path exists as subobject chain within obj 
    * 
    * @param obj {object} the object to search for <code>path</code> in 
    * @param path {String} the path to search within <code>obj</code>. oatgh must not start wirth the object itself. 
    * @return {boolean} whether <code>path</code> exists within <code>obj</code> or not 
    * example: to check if the windows document body has a fist item element you would use 
    * if (assertChain(window, "document.body.firstChild")) {} 
    * instead of 
    * if (window && window.document && window.document.body && window.document.body.firstChild) {} 
    */ 
    function assertChain(obj, path) { 
     var o = obj, 
      ret = ("object" === $.type(obj) && "string" === $.type(path)); 

     if (ret) { 
      $(path.split(".") || {}).each(function(ignore, value) { 
       ret = value in o; 
       if (ret) { 
        o = o[value]; 
       } 
       return ret; 
      }); 
     } 
     return ret; 
    } 

    var t = assertChain(dataItem, "dataItem.openSocial.embed.context.connectionsContentUrl") && dataItem.openSocial.embed.context.connectionsContentUrl; 

    dataItem.xcc = dataItem.xcc || {}; //Access it 

,我發現這個:

var isDefined = function(value, path) { 
    path.split('.').forEach(function(key) { value = value && value[key]; }); 
    return (typeof value != 'undefined' && value !== null); 
}; 

var t = {a: {a1: 33, a12: {aa1d: 444, cc: 3}}, b: 00}; 

var results = ''; 
['a.a12.cc', 'a.a1.cc'].forEach(function(path) { 
    results += 't[' + path + '] = ' + isDefined(t, path) + '\n'; 
}); 

document.body.appendChild(document.createElement('pre')).textContent = results; 

哪種方式最好?

+0

「最好」是什麼意思? –

+0

我必須說,這是一些三元論。 – Rajesh

+0

雖然問題不清楚,但可以使用'try catch'。 'var a = null;嘗試{a = el.openSocial.embed.context.openSocial.connections.generator.displayName} catch(ex){a =''}'。另外,如果目標僅僅是爲了獲得改進,[CodeReviews](http://codereview.stackexchange.com/)就是正確的選擇。 – Rajesh

回答

0

我對上面的代碼有一點改進。

我的函數返回給定的路徑屬性,或者undefined。更重要的是,當發現undefined停止迭代(的forEach將保持迭代,直到路徑數組的結束)

const assertProperty = (object, path) => { 
 
    if(typeof object !== 'object' || typeof path !== 'string') 
 
    return 
 
    
 
    let scrap = object 
 
    
 
    path.split('.').every((part) => scrap = scrap[part]) 
 
    
 
    return scrap 
 
} 
 

 
let test = { 
 
    a: { 
 
    b: { 
 
     c: { 
 
     d : { 
 
      e: {} 
 
     } 
 
     } 
 
    } 
 
    } 
 
} 
 

 
console.log(assertProperty(test, 'a.b.c.d')) 
 

 
console.log(assertProperty(test, 'a.b.c.d.e.f.g'))

在你的代碼,你可以用它喜歡:

var displayName = assertProperty(el, 'openSocial.embed.context.openSocial.connections.generator.displayName') || ''