detachEvent不使用命名内联函数 [英] detachEvent not working with named inline functions

查看:137
本文介绍了detachEvent不使用命名内联函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天在IE8中遇到了一个问题(注意我只需要支持IE)我似乎无法解释:当使用命名的匿名函数处理程序时,detachEvent不起作用。

I ran into a problem in IE8 today (Note that I only need to support IE) that I can't seem to explain: detachEvent wouldn't work when using a named anonymous function handler.

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
});

我最终发现改变onIframeReadyStateChange以使用arguments.callee(我通常会避免)而是解决了问题:

I eventually figured out that changing onIframeReadyStateChange to use arguments.callee (which I normally avoid) instead solved the issue:

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"
});

给出了什么?!第一个代码段不应该正常工作吗?

What gives?! Shouldn't the first snippet work fine?

推荐答案


第一个代码段不应该正常工作吗?

Shouldn't the first snippet work fine?

是的,可以说是应该的。但事实并非如此。 :-)幸运的是有一个简单的解决方法(并且比 arguments.callee 更好,有问题[见下文])。

Yes, arguably it should. But it doesn't. :-) Fortunately there's an easy workaround (and a better one than arguments.callee, which has issues [see below]).

问题在于命名函数表达式(NFE,这就是你所拥有的)在JScript(IE)中无法正常运行其他实现在野外。 Yuriy Zaytsev( kangax )对NFE进行了彻底调查,并写了这篇有用的文章关于它们。

The problem is that named function expressions (NFEs, which is what you have there) do not work correctly in JScript (IE) or several other implementations out in the wild. Yuriy Zaytsev (kangax) did a thorough investigation of NFEs and wrote up this useful article about them.

命名函数表达式是你给出的地方名称​​和的函数将函数语句用作右手值(例如,赋值的右手部分,或将其传递给函数,如 attachEvent ),如下所示:

A named function expression is where you give a function a name and use the function statement as a right-hand value (e.g., the right-hand part of an assignment, or passing it into a function like attachEvent), like this:

var x = function foo() { /* ... */ };

这是一个函数表达式,函数名为。可以说它应该工作,但在野外的许多实现中,包括IE的JScript,它没有。命名函数可以工作,匿名函数表达式可以工作,但不能命名函数表达式。 (编辑我不应该说不能正常工作,因为在某些方面他们会这样做。我应该说正常 ;更多在Yuriy的文章和我对你的后续问题的回答

That's a function expression, and the function is named. Arguably it should work, but in many implementations in the wild, including IE's JScript, it doesn't. Named functions work, and anonymous function expressions work, but not named function expressions. (Edit I shouldn't have said don't work, because in some ways they do. I should have said don't work properly; more in Yuriy's article and my answer to your follow-up question.)

相反,你必须这样做:

var x = foo;
function foo() { /* ... */ };

...毕竟,它确实会出现同样的情况。

...which does, after all, come to the same thing.

所以在你的情况下,只需这样做:

So in your case, simply do this:

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
}

这与您尝试的效果相同,但不会遇到实施问题。

That has the same effect as what you were trying to do, but without running into implementation problems.

(这稍微偏离主题,但是.. 。)你应该避免使用 arguments.callee 。在大多数实现中,使用它会带来大量性能开销,将函数调用减慢一个数量级(是的,真的;不,我不知道为什么)。它在ECMAScript 5的新严格模式中也是不允许的(而严格模式主要是一件好事)。

(This is slightly off-topic, but...) You're right to avoid using arguments.callee. In most implementations, using it carries a massive performance overhead, slowing down the function call by an order of magnitude (yes, really; and no, I don't know why). It's also disallowed in the new "strict mode" of ECMAScript 5 (and "strict mode" is mostly a good thing).

这篇关于detachEvent不使用命名内联函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆