2011-09-16 26 views
3

所以我使用一個對象在我的可選變量傳遞,像這樣:防範不確定參數

var foo = function (options) { 
      var options = options || {}; //provide a default, so that 
      var bar = options.bar || 42; //this doesn't fail on 'foo();' 
      //do stuff 
     }; 

的JSLint抱怨說我改寫選項,這就是我想要的東西,如果是falsy。實際上,我應該檢查它是否是Object,否則會拋出一個錯誤讓用戶知道發生了什麼。所以 - 在這張紙上 - 這裏有什麼好的形式?有人對此有所瞭解嗎?此外,我將如何去用這種模式在乾式風格中編寫一堆函數?

回答

6

首先,你不需要重新分配options參數給var。其次,對於某些值要小心這樣的:

var foo = function (options) { 
      options = options || {}; 
      var bar = options.bar || 42; 
      var baz = options.baz || 'fubar'; 
      }; 
foo({ bar: 0, baz: "" }); 

裏面foobar == 42 & baz == 'fubar'因爲0""是falsy。它可能會更好得更加詳細,以便更精確:

var foo = function (options) { 
      options = options || {}; 
      var bar = typeof options.bar == 'undefined' ? 42 : options.bar; 
      var baz = typeof options.baz == 'undefined' ? 'fubar' : options.baz; 
      }; 

但是,待幹後,您可以創建一個defaults對象,只是兩個對象擴展到settings對象:

// generic shallow object extension, mutates obj1 
var extend = function (obj1, obj2) { 
    for (var prop in obj2) { 
    if (obj2.hasOwnProperty(prop)) { 
     obj1[prop] = obj2[prop]; 
    } 
    } 
    return obj1; 
}; 

var foo = function (options) { 
    var defaults = { 
     bar: 42, 
     baz: 'fubar' 
     }, 
     settings = extend(defaults, options); 
}; 

由於您在此次調用中不再使用defaults,因此發生變異並不重要。使用這種方法:

foo();     // -> settings = { bar: 42, baz: 'fubar' } 
foo({ bar: 0 });   // -> settings = { bar: 0, baz: 'fubar' } 
foo({ bar: 0, baz: "" }); // -> settings = { bar: 0, baz: '' } 
+1

用於提及虛假值(和擴展)的+1 –

+0

使用'Object.keys'而不是'for ... in'循環,因爲它快了約9倍 – Raynos

+0

添加到'extend()'的某些類型檢查將會非常好。 – chelmertz

-1

不要用var來定義options。它已經在你的函數定義中定義了。

避免重複自己,你可以使用類似:

function defaultValue(expected, defaultValue) { 
    return expected || defaultValue; 
} 

然後

options = defaultValue(options, {}); 

你很難得到比你有什麼更簡潔,但...

+0

您評論說,'defaultValue'功能ISN實際上更簡潔,但是你還是建議了嗎?大量的函數調用會減慢程序的整體執行速度。 –

0

刪除選項行中的var和JSLint將停止抱怨。

這是因爲你有一個名爲options的參數,然後你試圖聲明一個名爲options的局部變量。您仍然可以設置默認值,如果它是falsey

options = options || {}; 

說實話,空在JavaScript合併是相當優良它自己。

你可以記住,如果你真的想要,你可以有點「異國情調」。所以,你的例子,如果你只是想options.bar或42:

(options || {})["bar"] || 42 

(記住,你可以點符號或陣列式的訪問JavaScript屬性)

這不是漂亮 - 但它只是一個例。或者,你可以這樣做:

(options || {"bar":42})["bar"] 

如果你有一個選項的默認設置,你可以這樣做:

(options || defaults)["bar"] 

:作爲一個不同的答案提到的,你要小心在某些值是錯誤的,你可能沒有意識到(即一個空字符串)之前。當然,有時這正是你想要的,但它只是要記住的東西:)

+0

所有可行的選項,但可讀性和可維護性也很重要。 – RobG

+1

在任何示例中都不需要計算訪問。 '(options || {})。bar || 42'將工作得很好。 –

0

的JSLint只是抱怨,因爲您使用var關鍵字,但選項已被定義。你可以刪除var,它不會抱怨。

爲了測試是否是選擇一個對象,你可以使用typeof options === 'object',但要注意數組和null也是對象,所以你可能想測試是這樣的:

typeof options === 'object' && options !== null && !(options instanceof Array) 
+0

在第一個測試中不需要===,因爲比較是帶字符串的字符串。爲什麼排除數組?在這種情況下,使用for..in遍歷它們的屬性是很好的。 – RobG