2012-10-21 16 views
13

Possible Duplicate:
If Javascript has first-class functions, why doesn’t this work?funzione di Alias ​​in javascript

Quando provo a fare una funzione di alias per document.getElementById come di seguito:

f = document.getElementById; 

Ma, quando provo a chiamare:

var e_fullname = f(“fullname”); 

È stato rizzati un errore: Could not convert JavaScript argument

E qui sotto è OK:

var e_fullname = f.call(document, “funname”); 

Puoi dirmi perché?

+2

avete un po 'insolite citazioni. Che editor stai usando? – 0x499602D2

+8

@ I programmatori reali di David usano Word –

+0

Non credo questo problema perché un editor. Devo solo capire come funziona Javascript? – vietean

risposta

20

Ci sono quattro modi di chiamare una funzione:

  1. Funzione invocazione: f(p1, p2)
  2. Method Invocation: obj.f(p1, p2)
  3. applicare o Chiamata invocazione: f.apply(obj, [p1, p2]), f.call(obj, p1, p2)
  4. Costruttore invocazione: new f(p1, p2)

In tutti questi casi, f è solo un riferimento (puntatore) a un oggetto funzione (un oggetto con una proprietà interna [[Call]]). Ciò che lo rende diverso in tutti questi casi è il modo in cui viene chiamata la funzione, e ciò conta molto.

Quindi, f è solo un riferimento all'oggetto getElementById, non c'è differenza tra document.getElementById e someOtherHTMLElement.getElementById; la funzione non trattiene un riferimento all'oggetto che lo fa riferimento.

Se si desidera associare un certo "proprietario" oggetto , utilizzare il metodo bind:

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

Si potrebbe utilizzare 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); 

'stato introdotto nel ES5, in modo da essere consapevoli di browser non ancora supportano questa versione di ECMAScript!

In alternativa è possibile utilizzare il metodo di jQuery proxy, aggiunta nella versione 1.4

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

Oppure si potrebbe delcare f come una funzione della propria (questa è una soluzione più prolisso).

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

Volevo solo sottolineare che il JavaScript la versione a cui ti riferisci è specifica di Mozilla. Se si stanno prendendo in considerazione altri browser, è più utile fare riferimento alla versione di ECMAScript. '.bind' è stato introdotto in ES5. –

+0

Grazie a @FelixKling l'ho cambiato nel testo. – clentfort

+1

L'ultimo non funziona, gli argomenti non possono essere ritrasmessi direttamente così. Devi fare qualcosa come 'document.getElementById.apply (documento, Array.prototype.slice.call (argomenti));' –

5

getElementById è un metodo su documento. Per chiamarlo, l'interprete deve avere il corpo della funzione stessa, l'oggetto da chiamare (documento nel tuo caso) e gli argomenti.

Quando si esegue f = document.getElementById, si sta copiando il corpo della funzione, ma non l'oggetto per richiamarlo.

Quando si esegue questa operazione:

f.call(document, “funname”); 

si sta fornendo sia l'oggetto di chiamarlo, e gli argomenti.

Se si desidera essere in grado di chiamare f direttamente, è necessario ottenere l'oggetto "documento" memorizzato in là in qualche modo. Il più semplice è:

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

Questo crea una chiusura che trattiene il valore del documento per te.

È inoltre possibile utilizzare bind() per fare la stessa cosa.