¿Por qué no puedo pasar “window.location.reload” como argumento para setTimeout?

3 minutos de lectura

Me encantaría conocer el error que veo en Safari y Chrome con la siguiente línea de código:

setTimeout(window.location.reload, 250);

Chrome informa:
Uncaught TypeError: Illegal invocation

Y Safari:
TypeError: Type error

En FireFox, el código funciona bien. Además, este código funciona bien en cada uno de los tres navegadores:

setTimeout((function() {
  window.location.reload();
}), 250);

Chrome y Safari no tienen problemas con este código:

var say_hello = function () { alert("hello") };  
setTimeout(say_hello, 250);  

que tiene de especial window.location.reload que causa este error?

(No estoy seguro si es útil o no, pero aquí hay un jsfiddle ilustrando esto)

avatar de usuario
Tomasz Nurkiewicz

Porque reload() necesidades window.location como this. En otras palabras, es un método de window.location. Cuando tu dices:

var fun = window.location.reload;

fun();

Estas llamando reload() función sin ninguna this referencia (o con implícito window referencia).

Esto debería funcionar:

setTimeout(window.location.reload.bind(window.location), 250);

Él window.location.reload.bind(window.location) parte significa: tomar window.location.reload función y devolver una función que, cuando se llame, utilizará window.location como this referencia dentro reload().

Ver también

  • ¿Cómo puedo pasar un argumento a una función llamada usando setTimeout?
  • ¿Por qué no funciona console.log cuando se pasa como parámetro a forEach?
  • Conservar la referencia ‘esta’ en el controlador de eventos del prototipo de javascript

  • Tiene mucho sentido. Bueno saber. ¿Alguien sabe por qué funciona en Firefox?

    – goggin13

    31 de mayo de 2012 a las 19:51

  • @ goggin13: interesante… no estoy seguro. Pero ciertamente esto no es portátil.

    – Tomasz Nurkiewicz

    31 de mayo de 2012 a las 19:54

  • Correcto, solo curiosidad. Gracias por la .bind explicación, muy informativo!

    – goggin13

    31 de mayo de 2012 a las 19:57

  • @ goggin13 Probablemente por la misma razón que ahora puedes hacer const log = console.log. El tiempo de ejecución puede haber enlazado previamente ese método para usted, ya que está destinado solo para el singleton (location o console)

    – Juan Mendes

    6 abr a las 15:53

Hay otra forma de hacer esto, bastante simple, y no es necesario hacer pasos adicionales, enlaces o cosas por el estilo. Cuando usa funciones de flecha en lugar de funciones comunes en JS, el this se incluye el contexto. Así que podrías hacer lo siguiente con la misma facilidad:

setTimeout(() => window.location.reload(), 250);

avatar de usuario
Esailija

Porque this debe estar obligado a location cuando usted llama reload. Es lo mismo que intentar:

var reload = window.location.reload;
reload();

this sería window en modo no estricto y undefined en modo estricto, ambos inválidos.

en navegadores no antiguos puedes hacer en su lugar:

reload.call( location )

o en tu ejemplo:

setTimeout( window.location.reload.bind( window.location ), 1000 )

Sin embargo, los IE más antiguos no admiten el enlace explícito en los objetos del host.

También obtiene esto para algunos métodos nativos que no son genéricos, como:

var a = function(){}.toString;
a();
TypeError: Function.prototype.toString is not generic

Algunos son genéricos:

var fakeArray = {0:1,1:2,length:2};
fakeArray.join = [].join;
fakeArray.join( " " );
"1 2"

Esto falla porque te falta el location contexto (la función this), al pasar a su manera. Usted tendría que bind el contexto, antes de poder usarlo así, por ejemplo con el método de vinculación de subrayado.js

var boundReload = _.bind(window.location.reload, window.location);
setTimeout(boundReload, 500)

Es lo mismo con cualquier otra función que generalmente se llama desde su objeto contenedor como console.log

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad