2012-05-31 17 views
29

me gustaría alguna información sobre el error que estoy viendo en Safari y Chrome con la siguiente línea de código:¿Por qué no puedo pasar "window.location.reload" como un argumento para setTimeout?

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 muy 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); 

Lo que es especial acerca de window.location.reload que causa este error?

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

Respuesta

49

Debido reload() necesidades window.location como this. En otras palabras, es un método de window.location. Cuando uno dice:

var fun = window.location. reload; 

fun(); 

Usted está llamando reload() función sin ninguna referencia this (o con referencia implícita window).

Esto debería funcionar:

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

La parte window.location.reload.bind(window.location) significa: tomar window.location.reload función y devolver una función que, cuando se le llama, se utilizará como window.locationthis referencia dentro reload().

Ver también

+0

Marcas sentido perfecto. Bueno saber. ¿Alguna suposición de por qué funciona en Firefox? – goggin13

+0

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

+0

Correcto, solo curiosidad. Gracias por la explicación '.bind', ¡muy informativa! – goggin13

3

Debido this debe estar enlazado a location cuando llame reload. Es lo mismo que tratar:

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

this habría window en modo no estricto y undefined en modo estricto que son ambos válidos.

en los navegadores antiguos no se pueden hacer en su lugar:

reload.call(location)

o en su ejemplo:

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

antigua IE no son compatibles con la unión explícita en el host objetos sin embargo.

También consigue esto para algunos métodos nativos que no son genéricos, tales 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" 
2

esto falla debido a que se está perdiendo el contexto location (la función de this), al pasarlo a su manera. Usted tendría que bind el contexto, antes de poder utilizar de esta manera, por ejemplo, con la underscore.js bind method

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

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

+0

No recomendaría traer una biblioteca entera para una función que ya existe de todos modos. – jbabey

+0

@jbabey tienes razón si supones que el navegador es compatible con JavaScript 1.8.5, donde se introdujo 'bind '. Para compatibilidad con versiones anteriores, me quedaría con underscore.js o, si a uno le gusta, Prototype. – Tharabas

+0

aplicar o llamar podría (y probablemente debería) utilizarse en lugar de obligar – jbabey

Cuestiones relacionadas