JavaScript:for循环生成音频动态URL时buttonColours[i]为undefined求助
嘿,这个问题是JavaScript新手非常容易踩的闭包陷阱,我来给你把原因和解决方案讲得明明白白!
为什么会出现undefined?
你代码里用var i声明循环变量,但var是函数级作用域的变量——整个循环里只有一个i,每次循环都会覆盖它的值。当你点击按钮的时候,循环早已经跑完了,此时i的值已经变成了buttonColours.length(也就是4),而buttonColours[4]根本不存在,自然就返回undefined啦。
另外还要提个小细节:你代码里的CSS样式切换是固定针对.red按钮的,不管点哪个按钮都是红色按钮变样式,这个也得改成对应颜色的按钮哦。
解决方案
这里给你三种常用的解决办法,任选其一都能搞定:
1. 用let代替var声明循环变量
let是ES6新增的块级作用域变量,每次循环都会创建一个全新的i,绑定到当前的循环迭代里,点击事件触发时就能拿到正确的索引:
var buttonColours = ["red","blue","green","yellow"]; var sounds = []; for (let i = 0; i < buttonColours.length; i++){ $("."+buttonColours[i]).click(function(event){ // 此时i是当前循环的正确索引 sounds[i]= new Audio("sounds/"+buttonColours[i]+".mp3"); sounds[i].play(); // 切换当前点击按钮的样式 $("."+buttonColours[i]).addClass("pressed"); setTimeout(function(){ $("."+buttonColours[i]).removeClass("pressed"); }, 200); }); }
2. 用立即执行函数(IIFE)创建独立作用域
如果需要兼容ES6之前的环境,可以用立即执行函数把每次循环的i值封装起来,形成独立的作用域:
var buttonColours = ["red","blue","green","yellow"]; var sounds = []; for (var i = 0; i < buttonColours.length; i++){ // 把当前的i作为参数传入IIFE,保存为currentIndex (function(currentIndex) { $("."+buttonColours[currentIndex]).click(function(event){ sounds[currentIndex]= new Audio("sounds/"+buttonColours[currentIndex]+".mp3"); sounds[currentIndex].play(); $("."+buttonColours[currentIndex]).addClass("pressed"); setTimeout(function(){ $("."+buttonColours[currentIndex]).removeClass("pressed"); }, 200); }); })(i); }
3. 用jQuery的each方法遍历数组
jQuery的each方法会自动为每个迭代项创建独立的作用域,代码也更简洁直观:
var buttonColours = ["red","blue","green","yellow"]; var sounds = []; $.each(buttonColours, function(index, colour) { $("."+colour).click(function(event){ sounds[index]= new Audio("sounds/"+colour+".mp3"); sounds[index].play(); $("."+colour).addClass("pressed"); setTimeout(function(){ $("."+colour).removeClass("pressed"); }, 200); }); });
内容的提问来源于stack exchange,提问作者Infinite-zero
相关产品推荐
相关产品推荐

