无法理解 Javascript 带有 for 循环代码的事件处理程序

Can't understand Javascript eventhandler with for loop code

我正在努力学习 JavaScript,我看到一段代码可以根据您按下的按钮更改网页的 css 样式。

我不明白 for 循环为什么或如何指示按下 按钮。这是 javascript 部分:

var buttons = document.getElementsByTagName("button");

var len = buttons.length;

for (i = 0; i < len; i++) {
  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

http://jsfiddle.net/qp9jwwq6/

我查看了网络和 w3 学校,但他们没有用 for 循环解释该代码。有人可以给我解释一下吗?

谢谢

让我们分解一下。

首先我们需要访问页面上的 DOM 元素,因此我们通过在 document 本身上使用一个方法来实现,该方法将 return 我们想要的元素操纵。

var buttons = document.getElementsByTagName("button");

buttons 变量将是页面上所有按钮的列表。我们想对所有按钮做一些事情,所以首先我们缓存列表的长度,即计算我们有多少个按钮。

var len = buttons.length;

然后我们基本上说:将 i 设置为 0,然后将其递增直到它等于我们拥有的按钮数量。

for (i = 0; i < len; i++) {

现在,要访问列表中的一个按钮,我们需要使用括号表示法。所以 buttons[0] 是第一个元素,buttons[1] 是第二个元素,依此类推。由于 i 从 0 开始,我们将 i 放在方括号中,以便在每次迭代时访问列表中的下一个按钮。

  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

这相当于做:

 buttons[0].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[1].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[2].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

// etc.

当然那是super效率低下,我们可能不知道页面有多少个按钮。所以我们把所有的按钮都放在那里,找出有多少,然后遍历每个按钮并为它分配一个事件处理程序以及一个新的 class.

现在,查看 onclick 处理程序本身,我们可以看到它首先在被单击的按钮中找到 HTML,将其转换为小写字母,并将其分配给一个变量:

var className = this.innerHTML.toLowerCase();

通过使用 this,我们确保每个按钮在单击时都知道它自己的内部HTML。我们不跟踪哪个按钮是哪个,我们只是告诉每个按钮检查它自己的内容。

然后它所做的是将 body HTML 元素的 class 更改为我们刚刚解析的任何内容

document.body.className = className;

假设你有类似的东西

<button>success</button>
<button>failure</button>
<button>warning</button>

单击第一个按钮会将 <body> 元素的 class 设置为 success,单击第二个按钮会将其设置为 failure,而第三个按钮会将其设置为warning.

第一行将所有按钮保存在一个名为 buttons 的变量中。这实际上是一个数组,因为页面上可以有多个按钮。然后你遍历每个按钮并定义一个应该在点击时执行的函数。假设您有 2 个按钮,那么按钮 [0] 和按钮 [1] 将获得功能。

首先,总的来说,这段代码的基础有点不稳定、不寻常且不稳健,所以不要指望你即将学习对 JavaScript 的任何强大洞察力或代码设计。

关于答案:

for 循环不会 "indicate" 按下了哪个按钮。相反,它遍历页面上的每个按钮元素并将 完全相同的 函数定义分配给每个元素的 onclick 属性。单击特定按钮元素时结束 运行 的代码(这里我说的是函数体)通过分配 CSS class 分配给 body 元素至 document.body.className.

您的问题是询问函数如何知道将哪个 class 名称分配给 document.body.className。该函数从按钮元素的 innerHTML 中获取 class 名称,可以作为 this.innerHTML 访问(因为在事件处理程序中,this 是对元素的引用触发事件发生)。 HTML <button> 元素有点特殊,虽然它通常是一个看起来很简单的按钮,但它也是一个非叶节点,这意味着它包含自己的 HTML .你可以在那里放很多东西,但在这个例子中,它们只有一个纯文本节点,它完全(或几乎完全)由 class 名称组成(Normal 代表一个,Changed 另一个)。这就是该函数如何获得特定于该按钮的 CSS class 名称;它从单击的 <button> 元素内的文本中获取它。

我在后面说 "nearly exactly" 是因为按钮文本和他们在 CSS 规则(即 normalchanged)。这就是为什么他们必须在分配 class 名称之前降低提取的按钮文本 (toLowerCase()) 的字母大小写。 CSS class 区分大小写(参见 Are CSS selectors case-sensitive?)。

正如我所说,这是不寻常的代码。在普通 HTML 文本和代码元数据(在本例中为 CSS classes)之间创建映射(尤其是不精确的映射!)是相当不可取的。