JavaScript事件处理程序 - 为什么会起作用?

4

我刚接触JavaScript,如下面的代码所示。我想为页面上的6个按钮创建事件处理程序。单击按钮时,下面的代码块的显示属性从“none”更改为“block”。为此,我需要将每个按钮与一个唯一的HTML部分(在这种情况下为具有唯一ID的标签- pt1、pt2等)相关联。

我为此苦苦挣扎了一段时间,并让下面的代码工作。这就是问题所在!事实证明,我完全错了。但是,作为新手,当它起作用时,我认为我正在做正确的事情。由于我花了几个小时在这上面,我需要知道为什么下面的代码可以工作(这样我会感到我学到了东西)。我将突出显示我自己无法理解为什么它能工作的代码部分。

var buttons = document.getElementsByClassName("CSS");

for (var i = 0; i < buttons.length; i++) {
    // Generate strings associated with the button ids and the event handlers for each button
    var buttonID = "button" + i;
    var clickHandlerID = "clickHandler" + i;
    var buttonEH = document.getElementById(buttonID);
    // Identify the button elements by id

    // As clickHandlerID is a string, to get the browser to recognise it as a function name
    var clickHandler = window[clickHandlerID];

    buttonEH.addEventListener("click", clickHandler, false);
}

/*****************************************************************************/

// Why does this work?
// clickHandler1, clickHandler2, etc are not referenced in my event handler.
// My botched attempt to create them in the event handler (var clickHandler = window[clickHandlerID];)
// resulted in "undefined" values (from console.log(clickHandler)).
// Yet it worked?!?! (I did eventually find the correct approach, a simple 10 line solution,
// but I am troubled that I don't understand what is going on here. Any help would be greatly appreciated!!)

/*****************************************************************************/


function clickHandler1 () {
    if (pt1.style.display === "block") {
        pt1.style.display = "none";
    } else {
        pt1.style.display = "block";
    }
}

function clickHandler2 () {
    if (pt2.style.display === "block") {
        pt2.style.display = "none";
    } else {
        pt2.style.display = "block";
    }
}
1个回答

3

var buttons = document.getElementsByClassName("CSS");

for (var i = 0; i < buttons.length; i++) {
    // Generate strings associated with the button ids and the event handlers for each button
    var buttonID = "button" + i;
    var clickHandlerID = "clickHandler" + i;
    var buttonEH = document.getElementById(buttonID);
    // Identify the button elements by id

    // As clickHandlerID is a string, to get the browser to recognise it as a function name
    var clickHandler = window[clickHandlerID];
    console.log(clickHandler);

    buttonEH.addEventListener("click", clickHandler, false);
}

/*****************************************************************************/

// Why does this work?
// clickHandler1, clickHandler2, etc are not referenced in my event handler.
// My botched attempt to create them in the event handler (var clickHandler = window[clickHandlerID];)
// resulted in "undefined" values (from console.log(clickHandler)).
// Yet it worked?!?! (I did eventually find the correct approach, a simple 10 line solution,
// but I am troubled that I don't understand what is going on here. Any help would be greatly appreciated!!)

/*****************************************************************************/


function clickHandler0 () {
    if (pt0.style.display === "block") {
        pt0.style.display = "none";
    } else {
        pt0.style.display = "block";
    }
}
function clickHandler1 () {
    if (pt1.style.display === "block") {
        pt1.style.display = "none";
    } else {
        pt1.style.display = "block";
    }
}

function clickHandler2 () {
    if (pt2.style.display === "block") {
        pt2.style.display = "none";
    } else {
        pt2.style.display = "block";
    }
}
#pt0, #pt1, #pt2, #pt3 {
    display: none;
}
<button id="button0" class="CSS">button 1</button>
<button id="button1" class="CSS">button 2</button>
<button id="button2" class="CSS">button 3</button>

<div id="pt0">PT1</div>
<div id="pt1">PT2</div>
<div id="pt2">PT3</div>

所有在顶层作用域定义的函数和变量都成为 window 对象的属性。因此,window['clickHandler1'] 等同于 clickHandler1。你的代码做了以下操作:

var clickhandler = window[clickHandlerID];

clickHandlerID被设置为像"clickHandler1""clickHandler2"等字符串时。

谢谢!你的答案非常清晰易懂。这也引起了最后一个问题:为什么在循环中的console.log(clickHandler)语句会返回"undefined"(放置在"var clickHandler = window[clickHandlerID];"语句之后)?我问这个问题是因为我怀疑你的答案就是实际发生的事情,但是"undefined"的返回值让我感到困惑。再次感谢! - myles
哦,亲爱的,难道我的 clickHandler 函数是在循环之后定义的吗?我猜这就是发生的事情了?老实说! - myles
不,函数定义应该被提升到开头。我正在努力弄清楚。 - Barmar
我无法重现您的 console.log 问题。我将代码放入我的答案中,包括日志语句,它能正确记录函数。我怀疑您可能打错了字。 - Barmar
谢谢。一个错字让我浪费了几个小时,也带来了很多困惑。现在我很高兴终于明白了发生了什么!! - myles

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