为什么我不能将“window.location.reload”作为参数传递给setTimeout?

时间:2012-05-31 19:24:43

标签: javascript cross-browser

我希望通过以下代码行了解我在Safari和Chrome中看到的错误:

setTimeout(window.location.reload, 250);

Chrome报告:
Uncaught TypeError: Illegal invocation

和Safari:
TypeError: Type error

在FireFox中,代码运行正常。此外,此代码在三种浏览器中都可以运行:

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

Chrome和Safari对此代码没有任何问题:

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

导致此错误的window.location.reload有什么特别之处?

(不确定它是否有用,但这里有jsfiddle说明了这一点)

4 个答案:

答案 0 :(得分:62)

因为reload()需要window.location作为this。换句话说 - 它是window.location的一种方法。当你说:

var fun = window.location. reload;

fun();

您正在调用reload()函数而没有任何this引用(或隐式window引用)。

这应该有效:

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

window.location.reload.bind(window.location)部分表示:接受window.location.reload函数并返回一个函数,该函数在调用时将使用window.location作为this内的reload()引用。< / p>

另见

答案 1 :(得分:3)

当您致电this时,location必须绑定到reload。这和尝试一样:

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

this在非严格模式下为window,在严格模式下为undefined且无效。

在非旧版浏览器中,您可以改为:

reload.call( location )

或在您的示例中:

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

较旧的IE不支持对主机对象进行显式绑定。

对于一些非通用的本地方法,您也可以得到这个,例如:

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

有些是通用的:

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

答案 2 :(得分:2)

这会失败,因为您错过了location上下文(函数的this),当您按自己的方式传递时。 您必须bind上下文,然后才能像这样使用它,例如使用underscore.js bind method

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

与通常从其中包含console.log

之类的对象调用的任何其他函数相同

答案 3 :(得分:2)

还有另一种方法可以做到这一点,非常简单,无需执行额外的步骤,绑定或类似的操作。当您使用箭头函数代替JS中的常用函数时,将包含this上下文。因此,您可以轻松地执行以下操作:

setTimeout(() => window.location.reload(), 250);
相关问题