Подтвердить что ты не робот

Почему я не могу передать "window.location.reload" в качестве аргумента для setTimeout?

Мне хотелось бы узнать про ошибку, которую я вижу в Safari и Chrome со следующей строкой кода:

setTimeout(window.location.reload, 250);

Отчеты Chrome:
Uncaught TypeError: Illegal invocation

И сафари:
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, иллюстрирующий это)

4b9b3361

Ответ 1

Потому что 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().

См. также

Ответ 2

Потому что 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"

Ответ 3

Это не удается, потому что вам не хватает контекста location (функция this), когда вы передаете его по-своему. Вам нужно будет bind контекст, прежде чем вы сможете использовать его так, например, с помощью метода связывания underscore.js

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

То же самое с любой другой функцией, которая обычно вызывается из нее, содержащей объект типа console.log