Pol*_*ant 2 javascript internet-explorer anonymous-function javascript-events
我今天在IE8中遇到了一个问题(注意我只需要支持IE)我似乎无法解释:使用命名的匿名函数处理程序时detachEvent不起作用.
document.getElementById('iframeid').attachEvent("onreadystatechange", function onIframeReadyStateChange() {
if (event.srcElement.readyState != "complete") { return; }
event.srcElement.detachEvent("onreadystatechange", onIframeReadyStateChange);
// code here was running every time my iframe's readyState
// changed to "complete" instead of only the first time
});
Run Code Online (Sandbox Code Playgroud)
我最终发现改变onIframeReadyStateChange以使用arguments.callee(我通常会避免)而不是解决了这个问题:
document.getElementById('iframeid').attachEvent("onreadystatechange", function () {
if (event.srcElement.readyState != "complete") { return; }
event.srcElement.detachEvent("onreadystatechange", arguments.callee);
// code here now runs only once no matter how many times the
// iframe's readyState changes to "complete"
});
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?!第一个代码段不应该正常工作吗?
T.J*_*der 10
第一个代码段不应该正常工作吗?
是的,可以说它应该.但事实并非如此.:-)幸运的是,有一个简单的解决方法(和一个更好的arguments.callee
,有问题[见下文]).
问题是命名函数表达式(NFE,这是你在那里)在JScript(IE)或其他几个实现中无法正常工作.Yuriy Zaytsev(kangax)对NFE进行了彻底的调查,并撰写了这篇有用的文章.
命名函数表达式是您为函数指定名称并将函数语句用作右侧值(例如,赋值的右侧部分,或将其传递给函数attachEvent
),如下所示:
var x = function foo() { /* ... */ };
Run Code Online (Sandbox Code Playgroud)
这是一个函数表达式,函数名为.可以说它应该可以工作,但是在野外的许多实现中,包括IE的JScript,它都没有.命名函数可以工作,匿名函数表达式可以工作,但不能命名函数表达式.(编辑我不应该说不工作,因为在某些方面他们这样做.我应该说不能正常工作 ;更多在Yuriy的文章和我对你的后续问题的回答.)
相反,你必须这样做:
var x = foo;
function foo() { /* ... */ };
Run Code Online (Sandbox Code Playgroud)
...毕竟,它确实来了同样的事情.
所以在你的情况下,只需这样做:
document.getElementById('iframeid').attachEvent("onreadystatechange", onIframeReadyStateChange);
function onIframeReadyStateChange() {
if (event.srcElement.readyState != "complete") { return; }
event.srcElement.detachEvent("onreadystatechange", onIframeReadyStateChange);
// code here was running every time my iframe's readyState
// changed to "complete" instead of only the first time
}
Run Code Online (Sandbox Code Playgroud)
这与您尝试执行的操作具有相同的效果,但不会遇到实现问题.
arguments.callee
(这有点偏离主题,但是......)你是正确的避免使用arguments.callee
.在大多数实现中,使用它会带来巨大的性能开销,将函数调用减慢一个数量级(是的,真的;不,我不知道为什么).它在ECMAScript 5的新"严格模式"中也是不允许的(而"严格模式"主要是一件好事).