JavaScript类中调用setInterval时this失效及多气泡运动实现问题
问题根因
this指向丢失:setInterval传入类方法作为回调时,方法内部的this会被绑定到全局window对象,而非Bubble类的实例,因此无法识别实例上的其他方法。- 多气泡无法同时运动:你当前只定义了单个全局
bubble变量和单个timer定时器,每次创建新气泡都会覆盖旧实例,无法存储多个气泡,也没法同步控制多个气泡的运动。
修复后的完整代码
JS代码(class_practice.js)
// 存储所有气泡实例 let bubbles = []; let can = document.getElementById("myCanvas"); let cm = can.getContext('2d'); let timer; function setupBubble(tempX, tempY, tempR) { if (tempX == undefined || tempY == undefined || tempR == undefined) { tempX = 20; tempY = 20; tempR = 20; } const newBubble = new Bubble(tempX, tempY, tempR); bubbles.push(newBubble); // 首次绘制新增气泡 newBubble.createBubble(newBubble.x, newBubble.y, newBubble.r); console.log(newBubble.x, newBubble.y, newBubble.r); } // 全局重置方法 function resetCanvas() { clearInterval(timer); cm.clearRect(0, 0, can.width, can.height); bubbles = []; } class Bubble { constructor(tempX, tempY, tempR) { this.x = tempX; this.y = tempY; this.r = tempR; } move(tempX, tempY) { this.x = tempX; this.y = tempY; } createBubble(tempX, tempY, tempR) { cm.beginPath(); cm.arc(tempX, tempY, tempR, 0, 2 * Math.PI); cm.stroke(); } moveRnd() { // 修复原代码y轴边界判断误用canvas宽度的bug this.x = Math.floor(Math.random() * (can.width - this.r * 2) + this.r); this.y = Math.floor(Math.random() * (can.height - this.r * 2) + this.r); console.log(this.x, this.y); } startRnd() { clearInterval(timer); // 箭头函数继承外层作用域this,同时统一遍历所有气泡执行运动逻辑 timer = setInterval(() => { cm.clearRect(0, 0, can.width, can.height); bubbles.forEach(bubble => { bubble.moveRnd(); bubble.createBubble(bubble.x, bubble.y, bubble.r); }) }, 1000); } stopRnd() { clearInterval(timer); } }
HTML代码调整(仅需修改Reset按钮的点击逻辑)
<!-- 把原Reset按钮改成调用全局重置方法 --> <button onclick="resetCanvas()">Reset</button>
功能说明
- 每次点击Create Bubble按钮都会新增一个气泡实例,不会覆盖旧实例
- 点击Random Movement按钮后,所有已创建的气泡会同时随机运动
- 点击Stop按钮所有气泡停止运动,点击Reset按钮清空画布和所有气泡实例
内容的提问来源于stack exchange,提问作者Nyaaaaaaaa
相关产品推荐
相关产品推荐

