对象方法中For loop失效求助:记忆小游戏数组生成失败
问题根源:对象方法里的
this指向跑偏了! 嘿,这个问题我太懂了——你遇到的情况几乎可以肯定是**this的上下文指向不对**导致的!
为什么会这样?
在JavaScript的对象方法里,this的指向不是固定的,它完全取决于你怎么调用这个方法:
- 如果直接调用对象的方法(比如
myGame.generateCards()),this会正确指向你的游戏对象; - 但如果把这个方法当作回调函数传给其他东西(比如
setTimeout、事件监听器addEventListener),或者用某种方式间接调用,this就会变成全局对象(浏览器里是window),在严格模式下甚至会变成undefined。
这时候你在for循环里用this.pairCount(或者你用来控制循环次数的属性),拿到的就是undefined,循环条件i < undefined不成立,自然就不会执行,最后返回空数组。
而你换成普通变量的时候,变量是在全局作用域或者外层函数作用域里,不受this指向的影响,所以循环能正常跑起来。
举个直观的例子对比
错误场景(this指向错误):
const MemoryGame = { pairCount: 3, generateCards() { let cards = []; // 这里的this如果不是指向MemoryGame,this.pairCount就是undefined for (let i = 0; i < this.pairCount; i++) { cards.push(i, i); } return cards; } }; // 直接调用没问题 console.log(MemoryGame.generateCards()); // [0,0,1,1,2,2] // 但作为定时器回调调用,this指向window,返回空数组 setTimeout(MemoryGame.generateCards, 1000); // 输出 []
正常场景(普通变量不受this影响):
let pairCount = 3; function generateCards() { let cards = []; for (let i = 0; i < pairCount; i++) { cards.push(i, i); } return cards; } // 不管怎么调用都正常 setTimeout(generateCards, 1000); // 输出 [0,0,1,1,2,2]
解决方法有这几种,选适合你的就行:
方法1:用箭头函数定义方法
箭头函数会继承外层上下文的this,不会被调用方式改变:const MemoryGame = { pairCount: 3, generateCards: () => { let cards = []; for (let i = 0; i < this.pairCount; i++) { cards.push(i, i); } return cards; } };方法2:在方法内部先保存正确的
this
把对象的this存到一个变量(比如self或者that)里,循环里用这个变量代替this:const MemoryGame = { pairCount: 3, generateCards() { const self = this; // 保存正确的this指向 let cards = []; for (let i = 0; i < self.pairCount; i++) { cards.push(i, i); } return cards; } };方法3:调用方法时用
bind绑定this
如果你需要把方法作为回调,可以用bind强制绑定对象的this:setTimeout(MemoryGame.generateCards.bind(MemoryGame), 1000);方法4:用Class来组织你的游戏代码
Class里的方法默认会绑定到实例,只要你不是把方法裸传给回调(可以用箭头函数包裹):class MemoryGame { constructor() { this.pairCount = 3; } generateCards() { let cards = []; for (let i = 0; i < this.pairCount; i++) { cards.push(i, i); } return cards; } } const game = new MemoryGame(); // 用箭头函数包裹回调,确保this指向game实例 setTimeout(() => console.log(game.generateCards()), 1000);
最后检查一下
你可以在方法的开头加个console.log(this),看看输出的是什么——如果不是你的游戏对象,那就是this指向的问题没错了!
内容的提问来源于stack exchange,提问作者Martz89
相关产品推荐
相关产品推荐

