火狐浏览器中JavaScript作用域的问题

3
<div id="myElement2"></div>

<script>
window.onload = function() {
    document.getElementById("myElement1").onclick = function() {
        for (i = 0; i < 2; i++) {
            document.getElementById("myElement2").onmouseover = func;
            function func() {alert("hello"); } } } }
</script>

在Chrome和IE中,当单击myElement1时,func会完美地附加到myElement2。然而,在Firefox中,当单击myElement1时,我收到一个错误消息,指出func未定义。
我应该注意的是,如果使用匿名函数代替func,则在所有3个浏览器中都可以正常工作。
我的问题是,Firefox在这方面如何处理范围与IE和Chrome不同?
Will.

1
如果函数声明在事件分配之前会发生什么? - Matchu
4个回答

5
我认为问题在于func是在一个块内被定义的。尝试通过JSLint运行您的代码,您会注意到以下问题:
  • 函数语句不能放置在块中。使用函数表达式或将语句移动到外部函数的顶部。
  • 'func'在定义之前就被使用了。
尝试分配一个函数表达式而不是定义一个函数并通过名称分配它,也许像这样:
document.getElementById("myElement2").onmouseover = function() {
    alert("hello")
};

谢谢你告诉我关于 JSLint。 - willat8
2
不要把JSLint说的一切都当作真理。但是,根据ECMAScript标准,函数语句不能放在if/for等块中。目前浏览器可以让它通过,但是你这样做时得到的行为将会有所不同。尽量避免。 - bobince
谢谢,我也遇到了同样的问题,Firefox在函数B内部的if语句中声明函数A时出错。通过将函数A直接移入B中,我的问题得以解决。 - lmeurs

3

看起来是一个很棒的页面,我已经收藏了它以便以后阅读。非常感谢。 - willat8

0
我建议将声明放在赋值之前,并使用变量来保存函数,而不是全局声明:
<script>
window.onload = function() {
    document.getElementById("myElement1").onclick = function() {
        for (i = 0; i < 2; i++) {
            var func = function() { alert("hello"); }
            document.getElementById("myElement2").onmouseover = func;
        }
    } 
}
</script>

0

你的作用域有问题,因为你的函数定义在一个函数内部。我通常将函数封装在一个对象中。你可能也不需要循环。

看一下:

<div id="myElement1"></div>
<div id="myElement2"></div>
<script type="text/javascript">

    window.onload = function() {
        document.getElementById("myElement1").onclick = function() {
                document.getElementById("myElement2").onmouseover = myFunctions.func;
         }
     }
    /* Function definitions */ 
    var myFunctions = new Object();
    myFunctions.func = function () {
       alert("hello"); 
    }
</script>

这是一个好主意,但我有很多小函数需要在使用它们的地方定义。 - willat8
我知道这样对你来说很方便。但是动态定义函数不是最佳实践。如果你在onclick内使用var func,那么就无法引用它,从而导致内存泄漏。作为最佳实践,你应该将函数绑定在某个位置,并在需要时通过将其设置为null来解构它。当你进入更多的前端编程领域时,应该考虑这些问题。 :) - jonycheung
啊,我明白为什么你会使用对象的想法。幸运的是,我定义的所有小函数中绝大多数在执行后都会从事件监听器列表中移除自己。这样做还会导致内存泄漏吗? - willat8
当你说“小”函数时,你在做什么?我从来没有遇到过必须在JS中定义任意函数并放弃它们的情况。如果你真的必须这样做,就像这样在操作结束时将它们全部设置为null:var func = function() { alert("hello"); } document.getElementById("myElement2").onmouseover = func; func = null; - jonycheung
谢谢你的建议。我正在尝试模拟一个桌面系统,目前正在专注于图标拖放。我从来没有想过我会不得不编写这么多的代码来实现这个功能,但这主要是为了通过做来教自己语言,我认为这是非常值得的。 - willat8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接