You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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;
      
  }
  
}

错误原因

  1. 固定循环次数不匹配数组长度:你写的for (let i = 0; i < 2; i++)是固定循环2次,但splice()会缩短数组长度。比如删掉一个元素后数组只剩1个元素,循环到i=1时bubble[1]不存在,直接报错。
  2. 正向遍历+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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:21:03