动态绑定带参数的addEventListener,传入players[i]显示undefined的问题求助
点击名称传递参数显示undefined?看这篇解决!
嘿,我猜你遇到的问题是:循环创建的名称元素,点击后控制台总是输出undefined,没法把正确的名称插入到输入框里对吧?这其实是var变量的作用域特性在搞怪,咱们一步步来解决它~
问题根源
你用var声明了循环变量i,它属于函数级作用域,整个循环里只有一个i变量。当循环结束时,i的值会变成2(因为循环条件是i < players.length,数组长度是2,所以i=2时退出循环)。等你点击div元素的时候,才会去取players[i],也就是players[2]——数组里根本没有这个索引,自然就输出undefined了!
修复方案
这里给你三种简单有效的解决方法,按需选择就行:
方法1:用let声明循环变量(最简洁)
把var i改成let i,let是块级作用域,每次循环都会创建一个独立的i变量,保存当前循环的索引值,点击时就能拿到正确的player名称:
var players = ["john","doe"]; function addPlayer(str) { console.log(str); document.getElementsByClassName("answerInput")[0].value += str; } for (let i = 0; i < players.length; i++) { var node = document.createElement("div"); var textnode = document.createTextNode(players[i]); node.appendChild(textnode); node.onclick = function() { addPlayer(players[i]); }; document.body.appendChild(node); }
方法2:用forEach遍历数组(更直观)
直接遍历players数组,每个元素都有自己的作用域,不用操心索引问题:
var players = ["john","doe"]; function addPlayer(str) { console.log(str); document.getElementsByClassName("answerInput")[0].value += str; } players.forEach(function(player) { var node = document.createElement("div"); var textnode = document.createTextNode(player); node.appendChild(textnode); node.onclick = function() { addPlayer(player); }; document.body.appendChild(node); });
方法3:用闭包保存索引(兼容旧浏览器)
如果需要兼容不支持ES6的旧浏览器,可以用立即执行函数创建闭包,把当前的索引值保存下来:
var players = ["john","doe"]; function addPlayer(str) { console.log(str); document.getElementsByClassName("answerInput")[0].value += str; } for (var i = 0; i < players.length; i++) { // 立即执行函数,把当前i作为参数传入 (function(index) { var node = document.createElement("div"); var textnode = document.createTextNode(players[index]); node.appendChild(textnode); node.onclick = function() { addPlayer(players[index]); }; document.body.appendChild(node); })(i); }
总结
最推荐用方法1或方法2,代码更简洁易读,也符合现代JS的写法。试试上面的代码,点击名称应该就能正确把值插入输入框啦!
内容的提问来源于stack exchange,提问作者N.Car
相关产品推荐
相关产品推荐

