2012-10-21 43 views
13

Possible Duplicate:
If Javascript has first-class functions, why doesn’t this work?別名功能的JavaScript

當我嘗試做一個別名功能document.getElementById如下:

f = document.getElementById; 

但是,當我嘗試撥打:

var e_fullname = f(「fullname」); 

有人惜售錯誤:Could not convert JavaScript argument

而且下面是OK:

var e_fullname = f.call(document, 「funname」); 

你能告訴我爲什麼嗎?

+2

你有一些不尋常的報價。你在用什麼編輯器? – 0x499602D2

+8

@David真正的程序員使用Word –

+0

我不認爲這個問題是因爲編輯器。我只是想了解Javascript是如何工作的? – vietean

回答

20

有兩種調用功能的四種方式:

  1. 函數調用:f(p1, p2)
  2. 方法調用:obj.f(p1, p2)
  3. 應用或電話調用:f.apply(obj, [p1, p2])f.call(obj, p1, p2)
  4. 構造函數調用:new f(p1, p2)

在所有這些情況下,f只是對函數對象(具有[[Call]]內部屬性的對象)的引用(指針)。在所有這些情況下,它們表現出不同的是函數的調用方式,而且這很重要。

所以,f只是到getElementById對象的引用,有document.getElementByIdsomeOtherHTMLElement.getElementById沒有什麼區別;該函數不會阻止對引用它的對象的引用。

如果你要綁定某個「所有者」對象,使用方法bind

var f = document.getElementById.bind(document); 
1

你可以使用bind

Creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function was called.

var f = document.getElementById.bind(document); 

它是在ES5推出,所以要知道瀏覽器尚未支持該版本的ECMAScript的!

正如你可以使用jQuery的proxy方法的替代方法,加入1.4

var f = ​$.proxy(document.getElementById, document); 

版本或者你可以delcare f它自己的功能(這是一個更詳細的解決方案)。

var f = function() { return document.getElementById(arguments); } 
+0

我只想指出JavaScript你所指的版本是特定於Mozilla的。如果您正在考慮其他瀏覽器,則參考ECMAScript版本會更有幫助。 '.bind'在ES5中引入。 –

+0

謝謝@FelixKling我在文中改變了它。 – clentfort

+1

最後一個不起作用,參數不能直接重新傳輸。你需要做一些像'document.getElementById.apply(document,Array.prototype.slice.call(arguments));' –

5

getElementById是文件上的方法。要調用它,解釋需要有函數體本身,對象調用它(在你的情況文件)和參數。

當你做f = document.getElementById,你複製功能體,而不是對象調用它。

當你這樣做:

f.call(document, 「funname」); 

你提供這兩個對象調用它,和論據。

如果你想能夠調用F直接,你需要得到存儲在那裏莫名其妙的「文檔」對象。最簡單的是:

var f = function(name){return document.getElementById(name)} 

這會創建一個閉包,它爲您保留文檔的值。

您還可以使用綁定()做同樣的事情。