javascript html5 google-chrome typeerror

javascript - "TypeError no detectado: invocación ilegal" en Chrome



html5 google-chrome (4)

Cuando ejecuta un método (es decir, función asignada a un objeto), dentro de él puede usar this variable para referirse a este objeto, por ejemplo:

var obj = { someProperty: true, someMethod: function() { console.log(this.someProperty); } }; obj.someMethod(); // logs true

Si asigna un método de un objeto a otro, this variable se refiere al nuevo objeto, por ejemplo:

var obj = { someProperty: true, someMethod: function() { console.log(this.someProperty); } }; var anotherObj = { someProperty: false, someMethod: obj.someMethod }; anotherObj.someMethod(); // logs false

Lo mismo sucede cuando asigna el método de window requestAnimationFrame a otro objeto. Las funciones nativas, como esta, tienen una protección incorporada que no se puede ejecutar en otro contexto.

Hay una Function.prototype.call() , que le permite llamar a una función en otro contexto. Solo tiene que pasarlo (el objeto que se utilizará como contexto) como primer parámetro de este método. Por ejemplo alert.call({}) da TypeError: Illegal invocation . Sin embargo, alert.call(window) funciona bien, porque ahora la alert se ejecuta en su alcance original.

Si usa .call() con su objeto así:

support.animationFrame.call(window, function() {});

funciona bien, porque requestAnimationFrame se ejecuta en el alcance de la window lugar de su objeto.

Sin embargo, utilizar .call() cada vez que desee llamar a este método, no es una solución muy elegante. En cambio, puede usar Function.prototype.bind() . Tiene un efecto similar a .call() , pero en lugar de llamar a la función, crea una nueva función que siempre se llamará en el contexto especificado. Por ejemplo:

window.someProperty = true; var obj = { someProperty: false, someMethod: function() { console.log(this.someProperty); } }; var someMethodInWindowContext = obj.someMethod.bind(window); someMethodInWindowContext(); // logs true

El único inconveniente de Function.prototype.bind() es que forma parte de ECMAScript 5, que no es compatible con IE <= 8 . Afortunadamente, hay un polyfill en MDN .

Como probablemente ya haya averiguado, puede usar .bind() para ejecutar siempre requestAnimationFrame en el contexto de la window . Tu código podría verse así:

var support = { animationFrame: (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame).bind(window) };

Entonces simplemente puede usar support.animationFrame(function() {}); .

Cuando uso requestAnimationFrame para hacer alguna animación nativa compatible con el siguiente código:

var support = { animationFrame: window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame }; support.animationFrame(function() {}); //error support.animationFrame.call(window, function() {}); //right

Llamando directamente a support.animationFrame le dará ...

Unkeught TypeError: Invocación ilegal

en Chrome. ¿Por qué?


En su código, está asignando un método nativo a una propiedad de objeto personalizado. Cuando llama a support.animationFrame(function () {}) , se ejecuta en el contexto del objeto actual (es decir, soporte). Para que la función native requestAnimationFrame funcione correctamente, debe ejecutarse en el contexto de la window .

Entonces, el uso correcto aquí es support.animationFrame.call(window, function() {}); .

Lo mismo ocurre con la alerta también:

var myObj = { myAlert : alert //copying native alert to an object }; myObj.myAlert(''this is an alert''); //is illegal myObj.myAlert.call(window, ''this is an alert''); // executing in context of window

Otra opción es usar Function.prototype.bind() que es parte del estándar ES5 y está disponible en todos los navegadores modernos.

var _raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame; var support = { animationFrame: _raf ? _raf.bind(window) : null };


También puedes usar:

var obj = { alert: alert.bind(window) }; obj.alert(''I´m an alert!!'');


tuve este error cuando tenía una conexión VPN, deshabilité la VPN y resolví el problema.