Array.find()处理Cell对象数组异常:邻居查找返回undefined求助
问题根源分析
你的问题出在Cell构造函数的执行时机上:当你在循环里调用new Cell(x, y)并立即push到cells数组时,构造函数内部的cells.find()是在当前Cell被添加到数组之前执行的——此时cells数组里只有已经创建好的前面的Cell,而当前Cell的右侧、下侧邻居(甚至部分左侧、上侧邻居)还没被创建出来,自然找不到对应的Cell,返回undefined。
举个例子:当创建(0, 0)这个Cell时,cells数组还是空的,四个方向的邻居都不存在;创建(1, 0)时,cells里只有(0, 0),所以只有左侧邻居能被找到,其他三个都是undefined。
解决方案:分两步创建单元格与邻居
解决思路很简单:先把所有Cell实例都创建并添加到cells数组里,等所有Cell都存在后,再逐个设置它们的neighbors属性。
方案1:基础版(使用find方法)
先修改Cell类,移除构造函数里的邻居初始化:
let cellWidth = 25; class Cell { constructor(x, y) { this.x = x * cellWidth; this.y = y * cellWidth; this.width = cellWidth; this.neighbors = []; // 先初始化空数组,后面再填充 } }
然后先创建所有Cell:
let cells = []; // 创建单元格(此时不设置邻居) for (let y = 0; y < rows; y++) { for (let x = 0; x < cols; x++) { cells.push(new Cell(x, y)); } }
最后遍历所有Cell,统一设置邻居:
// 为每个单元格查找并设置邻居 cells.forEach(cell => { cell.neighbors = [ // 上边邻居 cells.find(c => c.x === cell.x && c.y === cell.y - cell.width), // 右边邻居 cells.find(c => c.x === cell.x + cell.width && c.y === cell.y), // 下边邻居 cells.find(c => c.x === cell.x && c.y === cell.y + cell.width), // 左边邻居 cells.find(c => c.x === cell.x - cell.width && c.y === cell.y) ]; });
方案2:优化版(通过索引直接获取,效率更高)
如果你的网格比较大,find()方法每次都要遍历整个数组,效率会很低。可以给Cell添加网格索引属性,直接通过计算索引来获取邻居:
修改Cell类,添加gridX和gridY存储网格中的坐标索引:
class Cell { constructor(x, y) { this.gridX = x; // 网格中的x列索引 this.gridY = y; // 网格中的y行索引 this.x = x * cellWidth; this.y = y * cellWidth; this.width = cellWidth; this.neighbors = []; } }
然后设置邻居时,通过坐标偏移计算邻居的索引:
cells.forEach(cell => { const { gridX, gridY } = cell; // 四个方向的偏移量:[上, 右, 下, 左] const directions = [[0, -1], [1, 0], [0, 1], [-1, 0]]; cell.neighbors = directions.map(([dx, dy]) => { const neighborX = gridX + dx; const neighborY = gridY + dy; // 检查邻居是否在网格范围内 if (neighborX >= 0 && neighborX < cols && neighborY >= 0 && neighborY < rows) { // 计算邻居在cells数组中的索引(因为数组是按行存储的:行索引*列数 + 列索引) const neighborIndex = neighborY * cols + neighborX; return cells[neighborIndex]; } // 超出网格范围则返回undefined(也可以返回null,根据你的需求调整) return undefined; }); });
这个方法不需要遍历数组,直接通过索引访问,性能会好很多,尤其是大网格场景。
内容的提问来源于stack exchange,提问作者Jakub Papšo
相关产品推荐
相关产品推荐

