使用splice移除数组元素后,P5.js中spawn函数返回undefined的原因
P5.js气泡移除问题解决
问题描述
我上周刚开始学编程,用P5.js写了个随机生成气泡的程序,需求是气泡半径到指定值就从数组里删掉。一开始把半径设为0,结果只是重置半径循环;后来查资料用splice(),逻辑是半径大于200就从bubble数组删对应元素,但实际运行只能删一半,之后spawn()返回undefined,控制台报错:
🌸 p5.js says: [sketch.js, line 18] Cannot read property of undefined. Check the line number in error and make sure the variable which is being operated is not undefined.
原代码:
let bubble = []; function setup() { createCanvas(500, 500); for (let i = 0; i < 2; i++) { let x = random(width); let y = random(height); bubble[i] = new Bubble(x, y, 0); } } function draw() { background(0); for (let i = 0; i < 2; i++) { bubble[i].spawn(); bubble[i].update(); if (bubble[i].r > 200){ bubble.splice(i, 1); print('removed'); } } } //CLASSES class Bubble { constructor(x, y, r) { this.x = x this.y = y this.r = r; } spawn() { circle(this.x, this.y, this.r); noFill(); stroke(255); } update() { this.r += 5; } }
错误原因
- 固定循环次数不匹配数组长度:你写的
for (let i = 0; i < 2; i++)是固定循环2次,但splice()会缩短数组长度。比如删掉一个元素后数组只剩1个元素,循环到i=1时bubble[1]不存在,直接报错。 - 正向遍历+splice导致索引混乱:正向遍历数组时,删掉第i个元素后,后面的元素会自动前移一位。比如原来的
i=1元素变成i=0,但循环i会递增到1,直接跳过这个元素,导致只能删掉一半。
解决方案
方案1:反向遍历数组
从数组最后一位往前遍历,这样删掉元素不会影响前面未遍历的索引,避免跳过元素或访问undefined。
修正后代码:
let bubble = []; function setup() { createCanvas(500, 500); // 用push方法添加元素,比直接赋值索引更规范 for (let i = 0; i < 2; i++) { let x = random(width); let y = random(height); bubble.push(new Bubble(x, y, 0)); } } function draw() { background(0); // 反向遍历:从数组末尾开始,到0结束 for (let i = bubble.length - 1; i >= 0; i--) { bubble[i].spawn(); bubble[i].update(); if (bubble[i].r > 200) { bubble.splice(i, 1); print('removed'); } } } class Bubble { constructor(x, y, r) { this.x = x; this.y = y; this.r = r; } spawn() { noFill(); stroke(255); circle(this.x, this.y, this.r); } update() { this.r += 5; } }
方案2:使用filter()生成新数组
用filter()方法过滤掉不符合条件的气泡,生成新数组替代原数组,逻辑更简洁,也不会出现索引问题。
修正后代码:
let bubble = []; function setup() { createCanvas(500, 500); for (let i = 0; i < 2; i++) { let x = random(width); let y = random(height); bubble.push(new Bubble(x, y, 0)); } } function draw() { background(0); // 先更新并绘制所有气泡 bubble.forEach(bubbleItem => { bubbleItem.spawn(); bubbleItem.update(); }); // 过滤出半径<=200的气泡,替换原数组 bubble = bubble.filter(bubbleItem => bubbleItem.r <= 200); } class Bubble { constructor(x, y, r) { this.x = x; this.y = y; this.r = r; } spawn() { noFill(); stroke(255); circle(this.x, this.y, this.r); } update() { this.r += 5; } }
内容的提问来源于stack exchange,提问作者BUBSKI
相关产品推荐
相关产品推荐

