JS闭包对象共享状态异常:为何无法得到负分结果?
问题根源:闭包变量共享
你的代码中,studentHolberton是一个立即执行函数表达式(IIFE),内部的privateScore和name是整个IIFE的闭包变量——所有通过Object.create(studentHolberton)创建的实例,都会共用这两个变量。
实际执行流程:
- Jerry的4次奖励操作将
privateScore累加至4 - Dray的操作是在4的基础上计算:+1后变为5,再减3最终得到2,所以输出
Dray: 2,而非预期的-2
解决方案:生成独立实例的工厂函数
要让每个学生拥有独立的私有状态,需要把studentHolberton改成工厂函数,每次调用都会创建新的闭包环境,生成独立的私有变量:
function createStudentHolberton() { let privateScore = 0; let name = null; function changeScoreBy(points) { privateScore += points; } return { setName: (newName) => { name = newName; }, rewardStudent: () => { changeScoreBy(1); }, penalizeStudent: () => { changeScoreBy(-1); }, getScore: () => { return `${name}: ${privateScore}`; }, }; } // 创建独立实例 const jerry = createStudentHolberton(); jerry.setName('Jerry'); jerry.rewardStudent(); jerry.rewardStudent(); jerry.rewardStudent(); jerry.rewardStudent(); console.log(jerry.getScore()); // Jerry: 4 const dray = createStudentHolberton(); dray.setName('Dray'); dray.rewardStudent(); dray.penalizeStudent(); dray.penalizeStudent(); dray.penalizeStudent(); console.log(dray.getScore()); // Dray: -2
替代方案:ES6类+私有字段
如果使用现代JavaScript,也可以用ES6类结合私有字段(#前缀)实现,语法更清晰:
class StudentHolberton { #privateScore = 0; #name = null; #changeScoreBy(points) { this.#privateScore += points; } setName(newName) { this.#name = newName; } rewardStudent() { this.#changeScoreBy(1); } penalizeStudent() { this.#changeScoreBy(-1); } getScore() { return `${this.#name}: ${this.#privateScore}`; } } const jerry = new StudentHolberton(); jerry.setName('Jerry'); jerry.rewardStudent(); jerry.rewardStudent(); jerry.rewardStudent(); jerry.rewardStudent(); console.log(jerry.getScore()); // Jerry: 4 const dray = new StudentHolberton(); dray.setName('Dray'); dray.rewardStudent(); dray.penalizeStudent(); dray.penalizeStudent(); dray.penalizeStudent(); console.log(dray.getScore()); // Dray: -2
内容的提问来源于stack exchange,提问作者Saheedat
相关产品推荐
相关产品推荐

