2012-05-31 235 views
29

我喜歡的一些見解,我在Safari和Chrome上看到與下面的代碼行的錯誤:爲什麼我無法將「window.location.reload」作爲參數傳遞給setTimeout?

setTimeout(window.location.reload, 250);

鉻報道:
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說明這一點)

回答

49

因爲reload()需求window.locationthis。換句話說 - 這是一種方法window.location。當你說:

var fun = window.location. reload; 

fun(); 

你沒有任何this引用(或隱含window參考)調用reload()功能。

這應該工作:

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

window.location.reload.bind(window.location)部分是指:以window.location.reload功能和返回,調用它時,將使用內部reload()window.locationthis參考功能。

+0

使對象的任何其他功能相同完美的感覺。很高興知道。任何猜測爲什麼它在Firefox中起作用? – goggin13

+0

@ goggin13:有趣...不確定。但肯定這不是便攜式的。 –

+0

對,只是好奇。感謝'.bind'的解釋,非常翔實! – goggin13

3

因爲this必須綁定看到location當你調用reload。這是一樣的嘗試:

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

this將在非嚴格模式windowundefined嚴格模式,都是無效的。

非舊的瀏覽器,你可以做,而不是:

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

這是因爲你缺少location上下文(函數的失敗this),當傳遞你的方式。 你將不得不bind的背景下,纔可以與underscore.js bind method

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

這樣使用它,例如它與通常是從它被稱爲是一個包含像console.log

+0

我不會建議引入一個已經存在的函數的整個庫。 – jbabey

+0

@jbabey如果你認爲瀏覽器支持引入'bind'的JavaScript 1.8.5,那麼你是對的。爲了向後兼容,我會堅持使用underscore.js,或者如果喜歡它,Prototype。 – Tharabas

+0

apply或call可以(也可能應該)用來代替綁定 – jbabey

相關問題