2012-01-07 8 views
20

JavaScript se supone que tienen funciones de primera clase, por lo que este parece ser el siguiente debería funcionar:Si JavaScript tiene funciones de primera clase, ¿por qué no llamar a esta función en un trabajo variable?

var f = document.getElementById; 
var x = f('x'); 

pero fracasa en todos los navegadores, con un críptico mensaje de error diferente en cada uno. Safari dice "Escriba error". Chrome dice "Invocación ilegal". Firefox dice "No se pudo convertir el argumento de JavaScript".

¿Por qué?

Respuesta

19

Porque en las funciones de JavaScript no están encuadernados al contexto (this). Es posible utilizar bind():

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

Para aclarar esta respuesta, 'this' en' documento .getElementById() 'es' document', mientras que 'this' donde está ejecutando su scope es el alcance global, también conocido como' this' es el objeto 'window'. –

36

Cuando llame a obj.method() en Javascript, el método se pasa obj como this. Llamando al document.getElementById('x') con el conjunto this a document.

Sin embargo, si usted acaba de escribir f = document.getElementById Ahora tiene un nuevo referencia a la función, pero que la referencia ya no es "obligado" a document.

Por lo tanto, su código no funciona porque cuando llama al f como un nombre de función simple, termina vinculado al objeto global (window). Tan pronto como las entrañas de la función intenten usar this, descubren que ahora tiene un window en lugar de un document y, como era de esperar, no le gusta.

Usted puede hacer f trabajo si usted lo llama así:

var x = f.call(document, 'x'); 

que llama a f sino explícitamente establece el contexto de document.

La manera en que otros para solucionar este problema es utilizar Function.bind() que sólo está disponible en la ES5:

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

y es realmente sólo un atajo generalizado para la creación de su propio envoltorio que establece correctamente el contexto:

function f(id) { 
    return document.getElementById(id); 
} 
3

Usando operador propagación de ES6, también se podría tratar:

function f(){ 
    return document.getElementById(...arguments); 
}; 

Babel da esto:

function f() { 
    var _document; 
    return (_document = document).getElementById.apply(_document, arguments); 
}; 
Cuestiones relacionadas