Почему я не могу передать "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, иллюстрирующий это)
Ответы
Ответ 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