簡體   English   中英

在Javascript中正確獲取對象屬性

[英]Proper getting of an object property in Javascript

我正在一個大型的Javascript代碼庫中工作,目前亂七八糟的代碼依賴於流量控制的異常

function getChecklistUrl() {
    try {
        return dataLayerObject.config.checklist;
    } catch (e) {
        try {
            console.error('dataLayer', e);
        } catch (ignore) {}
    }
}

我可能偏愛條件邏輯,例如同一函數的這種實現

function getChecklistUrl() {
    if(typeof dataLayerObject == 'object'        &&
       'config' in dataLayerObject               &&
       typeof dataLayerObject.config == 'object' &&
       'checklist' in dataLayerObject.config     &&
       typeof dataLayerObject.config.checklist == 'object') {
        return dataLayerObject.config.checklist;
    }
    return null;
}

雖然后者感覺很長,但是當然可以編寫輔助函數來減少這種檢查的樣板。

那么前者是Javascript的慣用語嗎? 后來是脆弱的(跨越瀏覽器/場景)還是最好留給try / catch嗎? 或者前者只是懶惰的證據?

編輯

這些對象被假定為“普通”對象,例如var obj = {}所以我不相信我在這里關心原型鏈。

在javascript中檢查對象屬性的正確方法是Object.hasOwnProperty()方法。

例:

var Person = {
  first_name: 'Fred',
  last_name: 'Flintstone'
};

if ( 'object' === typeof Person && Person.hasOwnProperty('first_name' ) {
  window.alert('the property exists!');
}

編輯

要檢查嵌套對象屬性,可以嘗試這樣的方法:

function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments, 1);

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false

首先,您不需要檢查 property in object && typeof obj[property] == 'object' 兩個 property in object ,您只能使用typeof來處理這兩個檢查。 原因是,如果obj.property不存在, typeof將返回undefined

因此,您可以通過編寫一個檢查某些東西是否為對象的小實用程序函數來模塊化您的方法:

function isObject(o) {
    return typeof o == 'object' && o !== null; // take care of the corner case that typeof null == 'object'
}

然后只需在必要的對象鏈上使用它,通過檢查所有擁有的對象是否存在來查找屬性:

function getChecklistUrl() {
    if(isObject(dataLayerObject) && 
       isObject(dataLayerObject.config) &&  
       isObject(dataLayerObject.config.checklist)) { 

        return dataLayerObject.config.checklist;
    }
    return null;
}

 var dataLayerObject = { config: { checklist: ['array of stuff'] } } function isObject(o) { return typeof o == 'object' && o !== null; } function getChecklistUrl() { if (isObject(dataLayerObject) && isObject(dataLayerObject.config) && isObject(dataLayerObject.config.checklist)) { return dataLayerObject.config.checklist; } return null; } console.log(getChecklistUrl()[0]); 

這使得代碼更有條理,更容易閱讀,恕我直言。

您還可以為對象執行類似getter的操作,這些對象采用點分隔的字符串並返回屬性,如果屬性不存在,則為null:

function getObjProperty(obj, propString) {
    if(!isObject(obj) || !propString || typeof propString != 'string') {
        return null;                                 // make sure obj is an object and propString is a non-empty string
    } 

    var props = propString.split('.');
    for (var i = 0, l = props.length; i < l; i++) {
        var p = props[i];
        if(!isObject(obj[p])) { return null; }       // if current property isn't an object, return null
        obj = obj[p];                                // otherwise update the object to the next one down the property chain
    }
    return obj;
}

您可以使用它: getObjProperty(dataLayerObject, 'config.checklist');

 var dataLayerObject = { config: { checklist: ['array of stuff'] } }; function isObject(o) { return typeof o == 'object' && o !== null; } function getObjProperty(obj, propString) { if (!isObject(obj) || !propString || typeof propString != 'string') { return null; } var props = propString.split('.'); for (var i = 0, l = props.length; i < l; i++) { var p = props[i]; if (!isObject(obj[p])) { // return null; } // if current property isn't an object, return null obj = obj[p]; // otherwise update the object to the next one down the property chain } return obj; } console.log(getObjProperty(dataLayerObject, 'config.checklist')); 

或者您可以使用相當簡單的遞歸方法實現此目的

注意

上面的例子也檢查了原型鏈。 如果您不想這樣,則在檢查屬性是否為對象時應使用hasOwnProperty來檢查測試對象上是否存在該屬性。

前綴的答案顯示了這種方法的一種變體。

你可以做這樣的事情,如果你想要它簡短,但它不會檢查dataLayer是否是一個對象,所以如果它是一個帶有配置和清單的函數,它也會返回它。 但由於它是一個自定義對象,它可能不是一個問題。 如果需要,您可以添加“in”或“hasOwnProperty”檢查,如果您願意,可以使用三元組。

var getChecklistUrl = function getChecklistUrl() {
    return dataLayerObject && dataLayerObject.config && dataLayerObject.config.checklist || null;
}

您可以通過利用強制轉換來縮短它:

if ( typeof dataLayerObject == 'object' &&
     dataLayerObject.config &&
     dataLayerObject.config.checklist &&
     typeof dataLayerObject.config.checklist == 'object') {
  // do something
}

如果你並不真的需要檢查核對表實際上是一個對象,你可以擺脫過去的typeof 第一typeof是必要的,因為你的變量看起來可能是全球性的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM