本節書摘來華章計算機出版社《javascript應用程式設計》一書中的第2章,第2.5節,作者:eric elliott 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
在javascript中,執行函數的方式是在其引用的結尾處追加花括号,下面我們對highpass()函數做略微修改。
highpass()的入參包含一個必選參數number與一個可選參數cutoff。如果未傳入cutoff,函數會認為自己是作為方法在對象上(filter)調用,會使用對象(filter)中的屬性cutoff而非入參cutoff。
普通函數的調用:
警告: 一般來說,函數中的this始終是指向全局對象,除非你将函數作為對象的方法執行(使用點文法或者方括号)。是以在做函數調用時,最好先确認其this指向是否正确,以防像屬性指派這樣的操作污染全局對象。
方法調用将函數與對象關聯起來,像object.methodname()(點文法)、object['method name']()(方括号文法)都屬于方法調用。
當你通過點文法調用方法時,在方法中使用this,可以通路到對象的屬性。在上例中,将入參與filter對象上的cutoff屬性作比較,随後傳回false,因為3明顯是小于this.cutoff值。請牢記,this值的指向取決于方法在哪一個對象上執行。
在第二個例子中,call()方法(繼承自function.prototype)将highpass()方法代理到了filter2對象上,由于filter2對象中cutoff值是3而不是5,測試依然通過。
确切來說,call()方法存在于每一個函數中,理論上可以使用call()方法讓函數在任意對象上進行方法調用,換句話說,它将函數中的this指向了你所指定的對象。方法簽名如下:
其中context是你希望this所指向的對象,如果想傳入一組數組作為入參,可以使用apply():
誠然,call()與apply()方法非常實用,不過使用它們時,你需要格外小心,因為它們所綁定的this上下文指向是臨時的,每次調用都需要準确無誤地傳入,而且時刻得確定this能夠在目前函數作用域中通路到。不過每次調用都這麼做略顯麻煩,特别是在事件監聽器中。
bind()方法可以解決這個問題,它用來将函數的this指向與目标對象綁定。bind()方法是javascript語言規範中的一門新特性,最開始在prototype等javascript類庫中出現,随後在ecmascript5規範中被标準化,但是老版本的浏覽器對它的相容度不高,你可以考慮自己實作或者采用第三方類庫。
bind()方法的使用場景之一,将事件監聽器與對象綁定:
上述代碼示例很好了解,事件監聽器通過addeventlistener方法綁定至lightswitch的dom元素上。那麼問題來了,事件監聽器中的this指向并不是lightbulb對象,而是點選觸發時的dom元素,是以lightbulb的開關邏輯不會被執行。
打開界面上的開關按鈕,lightbulb.ison的值仍為false。下面來用bind()方法修複這個問題,僅需對toggle的指派方式做略微修改。
toggle = lightbulb.toggle.bind(lightbulb);
ok,現在lightbulb的開關可以響應來自使用者的操作了。