JQuery嵌套each循环中无法识别预定义全局数组winningLines问题
问题分析与解决:宾果游戏winningLines未定义错误
我想创建全局对象winningLines来追踪宾果游戏中已命中的线路,避免重复检查。在遍历.bingoCards的$.each循环里,我给每个卡片ID创建了对应的关联数组,此时console.log能正常输出这个对象;但进入嵌套的bingoLines[settings['game-type']]遍历循环后,winningLines[this.id]变成了undefined,触发错误TypeError: Cannot set properties of undefined (setting '0')。
出错代码
var winningLines = {}; function setEmptyWinningLines(){ $.each($('.bingoCards'), function(){ winningLines[this.id] = {}; console.log(winningBingoLines[this.id]);//object exists //Set the individual possibilities from bingoLines array for each card. $.each(bingoLines[settings['game-type']], function(lineNumber, spotsToHit){ console.log(winningLines[this.id]);//object undefined //Set each line to false. winningLines[this.id][lineNumber] = false;//Where the error occurs. });//end each bingoLines });//end each }//end function
问题成因
核心是**this的指向在嵌套循环中发生了变化**:
- 外层
$.each循环里,this指向当前遍历的.bingoCards元素,所以this.id是正确的卡片ID; - 进入内层
$.each循环后,this指向的是当前遍历的bingoLines数组元素,不再是卡片元素,此时this.id要么是undefined,要么是数组元素的无关属性,自然找不到winningLines中对应的键,导致winningLines[this.id]为undefined,赋值时触发报错。
解决方法
方法一:在外层循环缓存卡片ID
把当前卡片的ID存到变量中,内层循环直接使用这个变量,避免this指向混乱:
var winningLines = {}; function setEmptyWinningLines(){ $.each($('.bingoCards'), function(){ var cardId = this.id; // 缓存当前卡片ID winningLines[cardId] = {}; console.log(winningLines[cardId]); $.each(bingoLines[settings['game-type']], function(lineNumber, spotsToHit){ console.log(winningLines[cardId]); winningLines[cardId][lineNumber] = false; }); }); }
方法二:利用$.each的上下文参数
把外层的卡片元素作为上下文传入内层循环,通过自定义的上下文属性访问卡片ID:
var winningLines = {}; function setEmptyWinningLines(){ $.each($('.bingoCards'), function(){ winningLines[this.id] = {}; console.log(winningLines[this.id]); // 传入外层卡片元素作为内层循环的上下文 $.each(bingoLines[settings['game-type']], {card: this}, function(lineNumber, spotsToHit){ console.log(winningLines[this.card.id]); winningLines[this.card.id][lineNumber] = false; }); }); }
方法三:使用ES6箭头函数
箭头函数会继承外层作用域的this,无需额外缓存或传参(需项目支持ES6+语法):
var winningLines = {}; function setEmptyWinningLines(){ $.each($('.bingoCards'), function(){ winningLines[this.id] = {}; console.log(winningLines[this.id]); // 箭头函数的this与外层循环一致 $.each(bingoLines[settings['game-type']], (lineNumber, spotsToHit) => { console.log(winningLines[this.id]); winningLines[this.id][lineNumber] = false; }); }); }
内容的提问来源于stack exchange,提问作者user2108555
相关产品推荐
相关产品推荐

