单击按钮时收到undefined

时间:2017-07-30 16:11:29

标签: javascript dom

我有以下代码,当我点击一个按钮时,我希望警报显示prizes数组中的字符串,该字符串对应于等于按钮编号的索引。我目前收到“Fresh Laundry!”。

<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  for (var btnNum = 0; btnNum < prizes.length - 1; btnNum++) {
    document.getElementById('btn-' + btnNum).onclick = function() {
      alert(prizes[btnNum]);
    };
  }
</script>

5 个答案:

答案 0 :(得分:1)

您的代码存在与闭包有关的问题,在alert(prizes[btnNum])中使用的btnNum在循环结束后的值为2。如果你只是在事件处理程序中使用每个元素的id来从数组中获取奖励会更好,如下所示:

&#13;
&#13;
<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
    document.getElementById('btn-' + btnNum).onclick = function() {
      var id = this.id;
      alert(prizes[id.charAt(id.length-1)]);
    };
  }
</script>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

这是因为调用闭包时,btnNum已设置为32。

您可以这样做:

&#13;
&#13;
<script type="text/javascript">
  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  for (var btnNum = 0; btnNum < prizes.length - 1; btnNum++) {
    (function(_btnNum) {
      document.getElementById('btn-' + _btnNum).onclick = function() {
        alert(prizes[_btnNum]);
      }
    })(btnNum);
  }
</script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以尝试在按钮中设置一个值:

<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  for (var btnNum = 0; btnNum < prizes.length - 1; btnNum++) {
    document.getElementById('btn-' + btnNum).value = btnNum;
    document.getElementById('btn-' + btnNum).onclick = function() {
      alert(prizes[this.value]);
    };
  }
</script>

自己找你最喜欢的方法

答案 3 :(得分:0)

为什么不

  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  function clickHandler (btnNum) {
    alert(prizes[btnNum])
  };
<button id="btn-0" onclick="clickHandler(0)">Button 1!</button>
<button id="btn-1" onclick="clickHandler(1)">Button 2!</button>
<button id="btn-2" onclick="clickHandler(2)">Button 3!</button>

当然HTML中的onclick处理程序有点可怕,但是在设计代码示例背后没有更多背景,也可能。

为了让它更整洁,你可以尝试

var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
function clickHandler (event) {
  alert(prizes[this.id.replace('btn-', '')])
};
elems = document.getElementsByClassName('click-me');
for (var i=0; i<elems.length; i++) {
  elems[i].onclick = clickHandler;
}
<button id="btn-0" class="click-me">Button 1!</button>
<button id="btn-1" class="click-me">Button 2!</button>
<button id="btn-2" class="click-me">Button 3!</button>

答案 4 :(得分:0)

您遇到了closure的副作用。

闭包是保持声明它们的函数轨道的函数。在这种情况下,onclick函数是closure,它跟踪btnNum变量。随着btnNum在每次迭代后增加,onClick函数也会更新其实现中的btnNum,因此您每次都会看到Fresh Laundary

要解决此问题,您可以创建IIFE(立即调用的函数表达式)(function() {} }()并传递btnNum。这将限制闭包函数的范围,该函数仅引用预期的btnNum

<button id="btn-0">Button 1!</button>
<button id="btn-1">Button 2!</button>
<button id="btn-2">Button 3!</button>

<script type="text/javascript">
  var prizes = ['A Unicorn!', 'A Hug!', 'Fresh Laundry!'];
  for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
    (function(btnNum) {
      document.getElementById('btn-' + btnNum).onclick = function() {
        alert(prizes[btnNum]);
      };
    })(btnNum)
  }
</script>