为何forEach循环为Audio数组赋值src时所有元素均被修改?求助
遍历数组为Audio对象赋值src时所有元素属性同步变化的问题
问题描述
我想遍历字符串数组,将每个字符串赋值给对应Audio对象的src属性,让每个Audio对象拥有唯一的音效路径。但运行代码后发现,所有Audio元素的src都会被设置成最后一次迭代的路径,而非各自对应的值。
我的代码如下:
const srcArr = ['sounds/crash.mp3', 'sounds/kick-bass.mp3', 'sounds/snare.mp3', 'sounds/tom-1.mp3', 'sounds/tom-2.mp3', 'sounds/tom-3.mp3', 'sounds/tom-4.mp3']; const audios = new Array(srcArr.length).fill(new Audio()); audios.forEach((audio, index) => { audio.src = srcArr[index]; });
错误原因
问题不在forEach循环的机制上,你的forEach理解是对的——它确实会遍历数组每个元素并传入当前对象和索引。真正的问题出在**Array.fill()的使用上**:
当你执行new Array(srcArr.length).fill(new Audio())时,new Audio()只会执行一次,创建单个Audio实例。数组里的所有元素都是这个实例的引用,也就是说audios[0]到audios[6]指向的都是同一个内存地址里的Audio对象。所以你在forEach里修改任何一个元素的src,本质上都是在修改同一个对象的属性,最终所有元素的src都会变成最后一次赋值的结果。
正确写法
需要为数组的每个位置单独创建Audio对象,避免复用同一个实例,以下几种方式都可以:
方式1:使用map方法直接生成数组
const srcArr = ['sounds/crash.mp3', 'sounds/kick-bass.mp3', 'sounds/snare.mp3', 'sounds/tom-1.mp3', 'sounds/tom-2.mp3', 'sounds/tom-3.mp3', 'sounds/tom-4.mp3']; const audios = srcArr.map(src => new Audio(src));
方式2:用forEach循环手动创建并添加
const srcArr = ['sounds/crash.mp3', 'sounds/kick-bass.mp3', 'sounds/snare.mp3', 'sounds/tom-1.mp3', 'sounds/tom-2.mp3', 'sounds/tom-3.mp3', 'sounds/tom-4.mp3']; const audios = []; srcArr.forEach(src => { audios.push(new Audio(src)); });
方式3:用for循环初始化数组
const srcArr = ['sounds/crash.mp3', 'sounds/kick-bass.mp3', 'sounds/snare.mp3', 'sounds/tom-1.mp3', 'sounds/tom-2.mp3', 'sounds/tom-3.mp3', 'sounds/tom-4.mp3']; const audios = new Array(srcArr.length); for (let i = 0; i < srcArr.length; i++) { audios[i] = new Audio(srcArr[i]); }
总结
forEach循环的逻辑是正确的,问题源于对fill方法处理引用类型的特性不熟悉——fill对于对象、数组这类引用类型,只会复制引用而不会创建新实例。只要确保每个数组元素都是独立的Audio对象,就能实现预期效果。
内容的提问来源于stack exchange,提问作者Caleb Renfroe
相关产品推荐
相关产品推荐

