将变量的值传递给事件函数

Passing value of a variable to event function

我有一些 javascript 创建一些带有点击事件的按钮到一个函数,该函数传递该按钮的标识符。标识符是创建它们的代码中的一个变量。但是,变量是通过引用传递的,因此函数获取的值是变量的最后设置值,而不是创建按钮时的值。

这似乎是一个非常简单且常见的飞行员错误,但我无法在此处或更广泛的网络上找到任何答案。

在下面的示例中,我希望 Buttonclicked 函数中的 ClickedID 是创建按钮时 CreateButtons 函数中 ButtonID 的值(并显示在按钮的标题中),而不是 ButtonID 是什么时候功能完成。

function CreateButtons() {
  var Buttons = document.getElementById("Buttons");
  var Button = null;
  var ButtonID = 0;

  for (ButtonID = 0; ButtonID < 6; ButtonID++) {
    Button = document.createElement("button");
    Button.appendChild(document.createTextNode("Button " + ButtonID));
    Button.onclick = function() {ButtonClicked(ButtonID);};
    Buttons.appendChild(Button); }
}

function ButtonClicked (ClickedID) {
  alert("You clicked button " + ClickedID);
}
button {
  display: block;
  width: 150px;
  margin-bottom: 10px;
<button onclick="CreateButtons();">Create Buttons</button>
<div id="Buttons"></div>

<= ES5

您可以使用 IIFE(Immediately-invoked Function Expression)

轻松实现此目的

您正在获取循环结束的 buttonID,即 6。您可以做的是创建一个 IIFE,以便每次迭代创建一个新的 scope 和新的 ButtonID.

function CreateButtons() {
  var Buttons = document.getElementById("Buttons");
  var Button = null;
  let ButtonID = 0;

  for (ButtonID = 0; ButtonID < 6; ButtonID++) {
    (function(btnId) {                // change
      Button = document.createElement("button");
      Button.appendChild(document.createTextNode("Button " + btnId));
      Button.onclick = function() {
        ButtonClicked(btnId);
      };
      Buttons.appendChild(Button);
    })(ButtonID);                    // change
  }
}

function ButtonClicked(ClickedID) {
  alert("You clicked button " + ClickedID);
}
button {
  display: block;
  width: 150px;
  margin-bottom: 10px;
}
<button onclick="CreateButtons();">Create Buttons</button>
<div id="Buttons"></div>

来自 ES6 ## - 使用 let。 Let 和 const 声明了一个阻塞作用域的局部变量

只需创建一个新的局部作用域变量如下

for (let ButtonID = 0; ButtonID < 6; ButtonID++) {

function CreateButtons() {
  var Buttons = document.getElementById("Buttons");
  var Button = null;

  for (let ButtonID = 0; ButtonID < 6; ButtonID++) {
    Button = document.createElement("button");
    Button.appendChild(document.createTextNode("Button " + ButtonID));
    Button.onclick = function() {
      ButtonClicked(ButtonID);
    };
    Buttons.appendChild(Button);
  }
}

function ButtonClicked(ClickedID) {
  alert("You clicked button " + ClickedID);
}
button {
  display: block;
  width: 150px;
  margin-bottom: 10px;
}
<button onclick="CreateButtons();">Create Buttons</button>
<div id="Buttons"></div>

您可以使用 let 而不是 var 来解决这个问题:

for (let ButtonID = 0; ButtonID < 6; ButtonID++)

而不是

var ButtonID = 0;

您可以找到文档 here

let 创建块范围变量(因此附加到 for 循环),而 var 创建函数范围变量(附加到 CreateButton功能)。

var 的情况下,当 onclick 被调用时 ButtonID 是 6,因为循环已经完成。在 let 的情况下,循环中 ButtonID 的每个值都被保留并可供 onclick 处理函数访问。

此用例已详细解释 here。它包含两种解决方案 - 使用 let 和 IIFE(由 decpk 发布)

function CreateButtons() {
  var Buttons = document.getElementById("Buttons");
  var Button = null;

  for (let ButtonID = 0; ButtonID < 6; ButtonID++) {
    Button = document.createElement("button");
    Button.appendChild(document.createTextNode("Button " + ButtonID));
    Button.onclick = function() {ButtonClicked(ButtonID);};
    Buttons.appendChild(Button); }
}

function ButtonClicked (ClickedID) {
  alert("You clicked button " + ClickedID);
}
button {
  display: block;
  width: 150px;
  margin-bottom: 10px;
<button onclick="CreateButtons();">Create Buttons</button>
<div id="Buttons"></div>