模块模式下如何修改变量?井字棋tileCounter点击不递增问题
模块模式中点击事件无法递增计数器的问题
你遇到的核心问题是基本类型的值传递特性导致的,具体分析如下:
问题代码
const gameBoard = (() => { const tiles = document.querySelectorAll('.game-board > div') let tileCounter = 0; tiles.forEach(tile => tile.addEventListener('click', () => { tileCounter++; })) return {tileCounter}; })();
为什么点击事件里的tileCounter++不生效?
当你写return {tileCounter}时,JavaScript会把闭包内tileCounter的当前值(初始为0)复制一份作为返回对象的tileCounter属性。因为tileCounter是Number类型(基本类型),这里是值传递,不是引用传递。
这就导致:
- 点击事件里修改的是闭包内部的
tileCounter变量 - 你通过
gameBoard.tileCounter访问的是返回对象里的那个复制值,和闭包内的变量完全独立,所以看不到变化
而直接执行gameBoard.tileCounter++时,你是直接修改返回对象的tileCounter属性,自然能看到数值变化。
解决方法
有两种常用的修复方式:
方式1:用getter返回闭包内的最新值
通过定义getter方法,让每次访问gameBoard.tileCounter时都去读取闭包内的变量:
const gameBoard = (() => { const tiles = document.querySelectorAll('.game-board > div') let tileCounter = 0; tiles.forEach(tile => tile.addEventListener('click', () => { tileCounter++; })) return { get tileCounter() { return tileCounter; } }; })();
方式2:把计数器放在返回的对象中
将tileCounter直接挂载到返回的对象上,点击事件修改这个对象的属性(对象是引用类型,修改的是同一个内存地址的值):
const gameBoard = (() => { const tiles = document.querySelectorAll('.game-board > div') const boardState = { tileCounter: 0 }; tiles.forEach(tile => tile.addEventListener('click', () => { boardState.tileCounter++; })) return boardState; })();
内容的提问来源于stack exchange,提问作者Haskar1
相关产品推荐
相关产品推荐

