【问题标题】:"this" in javascript behaves differently in Internet Explorerjavascript 中的“this”在 Internet Explorer 中的行为不同
【发布时间】:2015-07-23 18:30:16
【问题描述】:

我有以下功能:

function toggleContent()
{
    var parent = this.parentElement;

    toggleClass(parent,"detailsAreVisible");
}

当用户单击某个按钮时,将调用此函数。绑定发生在普通的 javascript 中,如下所示:

var allTogglingButtons = document.querySelectorAll("[unhideicon],[hideicon]");
crossBrowserAddClickEvent(allTogglingButtons, toggleContent);

crossBrowserAddClickEvent 函数是修复另一个 IE 问题所必需的:

function crossBrowserAddClickEvent(array, functionName)
{   
    for(var i=0; i < array.length; i++)
    {
        if (array[i].addEventListener)
        {
            aray[i].addEventListener('click', functionName); 
        }
        else if (array[i].attachEvent)
        {
            array[i].attachEvent('onclick', functionName);
        }   
    }
}

这在 chrome 和 firefox 中运行良好,因为“this”变量设置为我在 toggleContent 函数内单击的按钮。但是,在 IE 中,“this”等于(默认)全局窗口/文档对象,当然在其上调用 .parentElement 会产生 null。为什么“this”不是点击按钮?

作为参考,我点击的“按钮”实际上是一个 svg 元素:

<svg unhideicon class="svgIcon">    ....    </svg>

【问题讨论】:

  • 为什么需要.attachEvent? IE8 doesn't support svg at all 这是最后一个不支持.addEventListener的版本
  • 好吧,我们很快就会用 img 替换 svg,但首先要做的事情是:)
  • 我还是很好奇... 正如已经写过的,SVG 从版本 9 开始仅受 IE 支持。那为什么需要使用.attachEvent? IE9+支持.addEventListener

标签: javascript html internet-explorer svg


【解决方案1】:

这是一个众所周知的 Exlorer 问题 你必须使用 EVENT 对象来获取你的调用者

function toggleContent(e)
{
    var event = e || window.event;
    var parent = (event.target || event.srcElement).parentElement;

    toggleClass(parent,"detailsAreVisible");
}

【讨论】:

  • window.event 中没有 .target 属性。您必须改用event.srcElement。
  • 而且e 中没有.srcElement。并非所有事情都可以在一行中完成... ;)
  • @Andreas (e &amp;&amp; e.target || window.event.srcElement).parentElement 怎么样?
  • 因为它更像是 Ninja-Coder xD
  • @Andreas 哦,我并没有真正推荐它作为一种方法——我(几乎)每次都会追求可读性——“并非所有事情都可以在一行中完成”听起来像是一个挑战; )
【解决方案2】:

实际问题不是因为 IE,而是因为 attachEvent 与 addEventListener 的不同之处。您应该注意到您的代码在 IE9+ 中运行良好,因为它将像 Chrome 和 Firefox 一样使用 addEventListener。由于 IE8 使用 attachEvent,所以需要进行一些不同的处理。

我的建议是您使用call 来调用该函数,这样您就可以定义this 是什么,在这种情况下您可以告诉它是您将事件附加到的元素:

// other code.
else if (array[i].attachEvent)
{
    var element = array[i];
    (function (el){
        el.attachEvent('onclick', function () {
            functionName.call(el);
        });
    })(element);
}

使用此方法意味着您不必更改您的toggleContent功能代码

Here is a working example


注意,我使用闭包来避免循环出现问题。因为单击事件函数在单击时运行,这意味着它将使用i 的当前值(而不是附加事件时设置的值)。因此,无论您单击哪个元素,i 将始终等于array.length。这不仅是错误的数字,而且无论如何都超出了范围。

【讨论】:

  • array[i] 将在click 事件触发时为undefined,因为i 将越界
  • 注意“i”变量和脚本片段,变量在声明后可能会改变,调用时,i=last value
  • 我很困惑。我认为当调用“addClickEvent”函数时javacript会放入正确的array[i]对象,为什么它会在我实际点击的时候尝试评估array[i]?
  • Musefan,由于 IE 9+,您的解决方案还需要放在 if/else 的其他部分(使用 addEventListener 而不是 AttachEvent 的部分)
猜你喜欢
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多