Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS中的addEventListener未按预期工作_Javascript_Html_Menu_Addeventlistener_Submenu - Fatal编程技术网

Javascript JS中的addEventListener未按预期工作

Javascript JS中的addEventListener未按预期工作,javascript,html,menu,addeventlistener,submenu,Javascript,Html,Menu,Addeventlistener,Submenu,请先略读代码 index.html是: <html><head><title>Home</title><script src="js/script.js"></script></head> <body onLoad="init()"> <ul class="sup" id="sup"> <li class="supitem"> <a href=

请先略读代码

index.html是:

<html><head><title>Home</title><script src="js/script.js"></script></head>
<body onLoad="init()">

<ul class="sup" id="sup">

    <li class="supitem">
        <a href="#" class="supcont">Home<div class="v"></div></a>
        <ul class="sub">
            <li class="subitem"><a href="#" class="subcont">Home1</a></li>
            <li class="subitem"><a href="#" class="subcont">Home2</a></li>
            <li class="subitem"><a href="#" class="subcont">Home3</a></li>
        </ul>
    </li>

    <li class="supitem">
        <a href="#" class="supcont">Blog<div class="v"></div></a>
        <ul class="sub">
            <li class="subitem"><a href="#" class="subcont">Blog1</a></li>
            <li class="subitem"><a href="#" class="subcont">Blog2</a></li>
            <li class="subitem"><a href="#" class="subcont">Blog3</a></li>
        </ul>
    </li>

</ul>

</body>
</html>
主页
script.js是:

function init() {
    var sky = 0;
    var sup         = document.getElementById("sup");
    var supitems    = sup.getElementsByClassName("supitem");

    for (var i = 0, ln = supitems.length; i < ln; i++) {
        var supconts = supitems[i].getElementsByClassName("supcont");
        var subs = supitems[i].getElementsByClassName("sub");
        var supcont = supconts[0];

        supcont.innerHTML = "SuperMenu"+i;

        if (subs.length > 0) {
            var sub         = subs[0];

            supcont.addEventListener("click",function() {
                toggleVisibility(sub); });

            supcont.style.background = "#"+sky+sky+sky;
            sub.style.background = "#"+sky+sky+sky;
            sky += 4;
        }
    }
}

function toggleVisibility(object) {
    object.style.visibility =
        (object.style.visibility == "hidden" ?"visible" :"hidden");
}
函数init(){
var-sky=0;
var sup=document.getElementById(“sup”);
var supitems=sup.getElementsByClassName(“supitem”);
对于(变量i=0,ln=supitems.length;i0){
var sub=subs[0];
supcont.addEventListener(“单击”,函数(){
切换可见性(sub);});
supcont.style.background=“#”+天空+天空+天空;
sub.style.background=“#”+天空+天空+天空;
天空+=4;
}
}
}
函数切换可见性(对象){
object.style.visibility=
(object.style.visibility==“隐藏”?“可见”:“隐藏”);
}
我想做的是当我按下supermenu时,所有子菜单的可见性都被切换。但我不知道我在哪里犯了错误。当我按下Supmenu0时,Supmenu1的子菜单被切换,而不是Supmenu1的子菜单。提前谢谢


另外,我认为问题出在addEventListener中。

这是一个常见问题,但我会尝试给出比我发现的更好的解释。当您将函数作为参数传递时(定义事件处理程序时),javascript此时不会计算函数,而是将函数与其父级
作用域的引用一起存储

在触发事件处理程序之前,不会对函数求值。此时,解释器将检查父
范围
中的
sub
的值。由于这总是在
for
循环完成后发生,因此它总是会找到
sub
的最后一个值,即当
for
循环完成时
sub
是什么。因此,所有事件侦听器都将使用
sub
的最后一个值

我们可以通过创建一个。替换此项:

supcont.addEventListener("click",function() {
    toggleVisibility(sub); });
为此:

(function(localSub) {
    supcont.addEventListener("click",function() {
        toggleVisibility(localSub);
    });    
})(sub);

这样做之所以有效,是因为我们通过调用IIFE将每个事件处理程序声明包装为一个新的父级
scope
。这迫使事件处理程序在IIFE内保留
范围的副本(称为在该
范围上创建闭包)。现在,当事件处理程序查找
localSub
时,它将在新的父
范围中找到它,并且它将具有我们想要的值。

这是一个常见问题,但我将尝试给出比我发现的更好的解释。当您将函数作为参数传递时(定义事件处理程序时),javascript此时不会计算函数,而是将函数与其父级
作用域的引用一起存储

在触发事件处理程序之前,不会对函数求值。此时,解释器将检查父
范围
中的
sub
的值。由于这总是在
for
循环完成后发生,因此它总是会找到
sub
的最后一个值,即当
for
循环完成时
sub
是什么。因此,所有事件侦听器都将使用
sub
的最后一个值

我们可以通过创建一个。替换此项:

supcont.addEventListener("click",function() {
    toggleVisibility(sub); });
为此:

(function(localSub) {
    supcont.addEventListener("click",function() {
        toggleVisibility(localSub);
    });    
})(sub);

这样做之所以有效,是因为我们通过调用IIFE将每个事件处理程序声明包装为一个新的父级
scope
。这迫使事件处理程序在IIFE内保留
范围的副本(称为在该
范围上创建闭包)。现在,当事件处理程序查找
localSub
时,它将在新的父
范围中找到它,并且它将具有我们想要的值。

谢谢,先生。顺便说一句,我刚刚学会了什么是结束。在这里留下链接以防万一:)谢谢,先生。顺便说一句,我刚刚学会了什么是结束。将链接留在此处以防万一:)