JavaScript闭包疑问:调用add方法后player.score为何未更新?
闭包场景中对象属性未同步更新的原因解析
你的问题核心在于对JavaScript原始值传递和闭包作用域的理解偏差,我们一步步拆解:
问题出在返回对象的score属性上
看createPlayer的返回语句:
return { score, add, report, };
这里的score是对函数内部let score = 0的原始值拷贝——因为score是数字(原始类型),当你把它作为对象属性返回时,相当于把当前的0值复制给了返回对象的score属性。从这一刻起,这个对象属性和闭包里的score变量就成了两个完全独立的东西,互不干扰。
add函数修改的是闭包内的变量,不是对象属性
再看add方法:
function add(amount) { score = score + amount; }
这里的score指向的是createPlayer函数作用域内的那个变量,调用player1.add(1)时,只会更新闭包里的score(变成1),但完全不会影响player1.score这个对象属性——它还是当初拷贝的0。
report能正确输出的原因
report函数直接访问的是闭包作用域里的score变量:
function report(label) { console.log(label, score); }
所以它能拿到add更新后的最新值,这也是为什么3: 1和4: 2是正确的。
如何让player1.score同步更新?
有两种常用方案:
方案1:使用getter方法
把返回对象的score改成getter,这样每次访问player1.score时,都会去读取闭包里的最新值:
function createPlayer() { let score = 0; function add(amount) { score += amount; } function report(label) { console.log(label, score); } return { get score() { return score; }, add, report, }; }
这种方式既保留了封装性(外部不能直接修改内部的score),又能获取到最新值。
方案2:用引用类型存储score
把score放在一个对象里(引用类型),这样返回的属性和闭包内的变量指向同一个引用:
function createPlayer() { const data = { score: 0 }; function add(amount) { data.score += amount; } function report(label) { console.log(label, data.score); } return { get score() { return data.score; }, add, report, }; }
本质和方案1类似,但用对象作为载体,不过getter的方式更直接。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

