闭包封装私有变量工厂的核心思路是用函数创建独立作用域隐藏变量,仅通过返回接口读写;每次调用工厂函数生成新闭包,确保实例间私有状态隔离,如count、timerid等不可被外部访问或修改。

闭包封装私有变量工厂的核心思路是:用函数创建独立作用域,把变量藏在里面,只通过返回的接口去读写。它不靠语法限制,而是靠 JavaScript 作用域链天然切断外部直接访问路径。
用工厂函数生成带私有状态的实例
工厂函数每次调用都新建一个闭包环境,确保每个实例的私有变量彼此隔离:
function createCounter(initial = 0) {
let count = initial; // 私有变量,外部无法触碰
return {
increment() { count++; },
decrement() { count--; },
value() { return count; },
reset() { count = initial; }
};
}
const c1 = createCounter(10);
const c2 = createCounter(100);
c1.increment();
console.log(c1.value(), c2.value()); // 11, 100
-
count不挂在this或返回对象上,外部查不到、改不了 -
c1和c2各自维护一份count,互不影响 - 所有方法共享同一份闭包,能安全操作
count
支持配置与副作用的增强写法
私有变量不止能存数字,还能存对象、函数、定时器 ID 等,适合封装更复杂的逻辑:
function createTimer(label) {
let startTime = 0;
let elapsed = 0;
let isActive = false;
let timerId = null;
return {
start() {
if (!isActive) {
startTime = Date.now() - elapsed;
isActive = true;
timerId = setInterval(() => {
elapsed = Date.now() - startTime;
}, 10);
}
},
stop() {
if (isActive) {
clearInterval(timerId);
isActive = false;
}
},
getElapsed() {
return Math.round(elapsed / 1000); // 秒
},
label: label // 只读公开字段,非私有
};
}
const workoutTimer = createTimer("健身");
workoutTimer.start();
// …稍等几秒后
console.log(workoutTimer.getElapsed()); // 比如 5
- 私有状态包括
startTime、elapsed、isActive、timerId,全部对外不可见 -
start/stop方法能精准控制内部资源,getElapsed只暴露必要结果 -
label是显式挂载的公开属性,和私有变量完全解耦
注意几个关键细节
- 不要把私有变量直接赋给返回对象的属性(比如
{ _count: count }),那只是快照值,不是实时引用 - 避免在返回对象里用
this.count,因为没构造实例,this很可能指向意外对象 - 如果需要多个实例共用方法逻辑(节省内存),可以把方法抽到工厂外,再通过参数传入私有状态
- 调试时 DevTools 能看到闭包变量,但运行时代码无法绕过作用域链访问——这是防误用,不是防攻击
不复杂但容易忽略。











