2006年11月29日

Function.prototype.call() and Function.prototype.apply()

JavaScript 調用 function object 的方式,除了傳統的 () 算符 [若用 C++ 的表達方式,即 operator() ],還可以藉由 call()apply() 兩種個體行為調用。


call()apply() 的差別主要在於 call() 只接受一個參數,即 call(thisArg) ;而 apply() 接受兩個參數,即 apply(thisArg, argArray) 。透過 call()apply() 調用函數的主要目的,在於改變函數內部的 this 名稱所指涉的對象。對一般函數而言,當 programmer 在函數內部使用 this 名稱時,指涉對象是 global objectglobal object 是運行環境中最頂層的個體,在瀏覽器環境中,global object 就是 window 此一個體。但是 call()apply() 可以改變 this 名稱所指涉的對象。

If thisArg is null or undefined, the called function is passed the global object as the this value. Otherwise, the called function is passed ToObject(thisArg) as the this value. ECMAScript Language Specification - Standard ECMA-262 3rd Edition. 15.3.4.3 & 15.3.4.4

首先,先來一段測試程式實證上面的標準規範內容。

結果證實規範內容所言無誤。因此,我們可以利用 call()apply() 改變函數內部的 this 名稱所指涉的對象。此一技巧最常運用在事件處理函數中,例如《Rendering images with title and box》就是這種技巧的實踐。在該例中,使用 call() 調用 renderImage() ,而將圖像索引值設定為屬性 myIndex 。其實像這種需要傳遞參數的情形,可以改用 apply() ,將要傳遞給 function object 的參數按順序放置在 apply() 行為的第二個 argArray 參數中。因此《Rendering images with title and box》用 apply() 改寫如下所示。

由於 apply() 的第二個 argArray 參數必須是陣列形式,所以要將 i 放入陣列中。其次, apply() 是按照變數在 argArray 陣列中的順序代換參數列的變數,故參數列的第一個參數內容,等於 argArray 中的第 0 個元素,以下類推。因此在上例中 renderImage(index) 中的 index 等於 argArray 中的第 0 個元素 (即 i) 。


Posted by shirock at 樂多Roodo! │23:57 │回應(1)引用(1)JavaScript
樂多分類:網路/3C 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/2532303
引用列表:
在 JavaScript 中欲實踐此技法須:理解什麼是 Function object 及匿名函數;理解 operator() 的用法;理解如何以 Function.call()/Function.apply() 改變 this 的指涉對象
The practice of anonymous recursion function in JavaScript【石頭閒語】 at 2007年02月13日 01:39
回應文章
The call method takes one or more arguments, thisArg and (optionally) arg1, arg2 etc, and performs a function call using the [[Call]] property of the object. If the object does not have a [[Call]] property, a TypeError exception is thrown. The called function is passed arg1, arg2, etc. as the arguments.
ECMAScript Language Specification - Standard ECMA-262 3rd Edition. 15.3.4.4
Posted by LungZeno at 2008年10月25日 06:45