¿Por qué ciertas llamadas a funciones se denominan "invocaciones ilegales" en JavaScript?


96

Por ejemplo, si hago esto:

var q = document.querySelectorAll;

q('body');

Recibo un error de "Invocación ilegal" en Chrome. No puedo pensar en ninguna razón por la que esto sea necesario. Por un lado, no es el caso de todas las funciones de código nativo. De hecho puedo hacer esto:

var o = Object; // which is a native code function

var x = new o();

Y todo funciona bien. En particular, he descubierto este problema al tratar con documentos y consolas. ¿Alguna idea?



1
el posible duplicado de la función de alias
HoLyVieR

Respuestas:


158

Es porque ha perdido el "contexto" de la función.

Cuando usted llama:

document.querySelectorAll()

el contexto de la función es documenty será accesible thismediante la implementación de ese método.

Cuando simplemente llamas q, ya no hay contexto, sino el windowobjeto "global" .

La implementación de querySelectorAllintenta usar thispero ya no es un elemento DOM, es un Windowobjeto. La implementación intenta llamar a algún método de un elemento DOM que no existe en un Windowobjeto y, como era de esperar, el intérprete llama a foul.

Para resolver esto, use .binden versiones más recientes de Javascript:

var q = document.querySelectorAll.bind(document);

lo que asegurará que todas las invocaciones posteriores de qtengan el contexto correcto. Si no lo tiene .bind, use esto:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}

3
Oh, buena decisión. Tiene razón porque puedo hacer: q.apply (document, ['body']); y funciona.
user1152187

Tenga en cuenta que esto no es necesario para las funciones integradas en IE. Por ejemplo, console.log no tiene un método de aplicación allí.
hugomg

@Alnitak: Sí, funciona en todas partes excepto en IE y es por eso que a menudo debería pasar argumentos normalmente, como en function q(x){ return document.querySelectorAll(x); }. Otra cosa que realmente me gusta de los objetos del navegador IE es que algunos de ellos lanzan una excepción solo si intentas leer una propiedad de ellos, ¡así que necesitas probar características con en if( 'funcname' in browserobject)lugar de lo habitual if(browserobject.funcname)!
hugomg

Excelente respuesta, estaba realmente confundido por este fenómeno, exactamente la misma situación que OP.
temporary_user_name

1
Alucinado. Gracias.
rb-

1

En mi caso, se produjo una invocación ilegal debido al paso de una variable no declarada para que funcione como argumento. Asegúrese de declarar la variable antes de pasar a la función.


declarar la variable no tendrá sentido en este caso particular, ya que se está produciendo una invocación ilegal, ya que el método dependiente de dom se llama fuera del contexto de DOM, porque en el momento en que se hace q = documento, algo el somethingmétodo pierde el contexto del documento
Anshul Sahni


0

Una solución más concisa:

const q=s=>document.querySelectorAll(s);
q('body');
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.