JavaScript中如何修改作为函数参数传入的全局变量的值?
问题:修改作为函数参数的全局变量值失效
场景与问题
我正在制作一个仅供个人使用的音乐能力测试,有数百个按钮对应各自的音频文件,要求每个音频最多播放两次,且播放时不能点击对应按钮。
原本功能正常,但将函数优化为带参数的形式后,限制播放次数的逻辑失效:全局变量canPlayPitch01作为参数传入playAudio函数后,函数内的递增操作无法修改原全局变量,导致if (canPlay < 2)判断失去作用。
我的代码
JavaScript代码
function playAudio(audioFile, canPlay) { if (canPlay < 2 && audioFile.paused) { canPlay = canPlay + 1; audioFile.play(); } else { if (canPlay >= 2) { alert("This audio has already been played twice."); } else { alert("Please wait for the audio to finish playing."); } } } const btnPitch01 = document.getElementById("btnPitch01"); const audioFilePitch01 = new Audio("../aud/Pitch01.wav"); var canPlayPitch01 = 0; btnPitch01.addEventListener("click", function() { playAudio(audioFilePitch01, canPlayPitch01); });
HTML代码
<body> <button id="btnPitch01">Play Pitch01</button> <button id="btnPitch02">Play Pitch02</button> <script src="js/js-master.js"></script> </body>
原因
JavaScript中,数字属于基本数据类型,当你把全局变量canPlayPitch01作为参数传入函数时,传递的是变量的值副本。函数内修改canPlay只是修改这个副本,不会影响原全局变量的值。
解决方案(保留参数传递思路)
方法1:用对象包裹播放次数(推荐)
利用对象是引用类型的特性,传递对象的引用,修改对象的属性会直接影响原对象:
修改全局变量定义:
// 用对象存储播放次数 var canPlayPitch01 = { count: 0 };
修改playAudio函数:
function playAudio(audioFile, canPlay) { if (canPlay.count < 2 && audioFile.paused) { canPlay.count += 1; // 修改对象属性,会同步到全局对象 audioFile.play(); } else { if (canPlay.count >= 2) { alert("This audio has already been played twice."); } else { alert("Please wait for the audio to finish playing."); } } }
调用方式不变,依然传递canPlayPitch01即可。
方法2:返回修改后的次数并赋值给全局变量
让函数返回修改后的播放次数,在调用时重新赋值给全局变量:
修改playAudio函数:
function playAudio(audioFile, canPlay) { if (canPlay < 2 && audioFile.paused) { canPlay += 1; audioFile.play(); } else { if (canPlay >= 2) { alert("This audio has already been played twice."); } else { alert("Please wait for the audio to finish playing."); } } return canPlay; // 返回修改后的次数 }
修改事件监听代码:
btnPitch01.addEventListener("click", function() { // 将函数返回的新值赋值给全局变量 canPlayPitch01 = playAudio(audioFilePitch01, canPlayPitch01); });
更适合大量音频的优化建议
如果要处理数百个音频,写几百个全局变量会非常繁琐,推荐用类封装每个音频的相关逻辑:
class AudioPlayer { constructor(btnId, audioUrl) { this.btn = document.getElementById(btnId); this.audio = new Audio(audioUrl); this.playCount = 0; // 绑定点击事件 this.btn.addEventListener("click", () => this.play()); } play() { if (this.playCount < 2 && this.audio.paused) { this.playCount += 1; this.audio.play(); } else { if (this.playCount >= 2) { alert("This audio has already been played twice."); } else { alert("Please wait for the audio to finish playing."); } } } } // 初始化每个音频 new AudioPlayer("btnPitch01", "../aud/Pitch01.wav"); new AudioPlayer("btnPitch02", "../aud/Pitch02.wav"); // 后续新增音频只需一行代码即可
这种方式无需全局变量,每个音频的状态独立管理,维护起来更轻松。
内容的提问来源于stack exchange,提问作者DissonantSynth
相关产品推荐
相关产品推荐

