工厂函数利用闭包隐藏私有变量和函数,返回对象的方法可访问但外部无法直接访问;每次调用创建独立作用域,支持多实例隔离与配置;需避免暴露私有引用。

在工厂函数中利用闭包隐藏内部实现,核心是让工厂函数返回一个对象(或函数),该对象的方法能访问工厂函数作用域内的私有变量和函数,而外部无法直接访问这些私有成员。
闭包让私有数据“驻留”在内存中
工厂函数执行时创建的局部变量,在函数返回后不会被销毁,因为返回的函数(方法)仍持有对其的引用。这就是闭包——内部函数记住并可以访问其词法作用域中的变量。
- 私有变量定义在工厂函数体内,不在返回对象上暴露
- 所有方法都定义在工厂函数内,自然能读写这些变量
- 外部只能通过返回对象上的公有方法间接操作,无法绕过逻辑
典型写法:返回带方法的对象
这是最常用也最清晰的方式。工厂函数内部封装状态和逻辑,只暴露可控接口:
function createCounter() {
let count = 0; // 私有状态,外部不可访问
return {
increment() { count++; },
decrement() { count--; },
getValue() { return count; }
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getValue()); // 1
console.log(counter.count); // undefined —— 无法直接访问
进阶用法:支持配置与多实例隔离
工厂函数可接收参数,为每个实例定制初始状态或行为,且各实例的私有数据完全独立:
立即学习“Java免费学习笔记(深入)”;
- 每次调用工厂函数都会新建一个作用域,生成独立的闭包环境
- 适合创建多个互不干扰的对象,比如不同用户的权限管理器、独立的缓存实例
- 可在内部定义辅助函数(如验证、格式化),仅供公有方法调用
例如:
function createUserManager(initialUsers = []) {
const users = [...initialUsers]; // 私有数组
function isValidEmail(email) {
return email.includes('@'); // 内部工具函数,外部不可见
}
return {
add(user) {
if (isValidEmail(user.email)) users.push(user);
},
list() {
return [...users]; // 返回副本,避免外部修改原始数据
}
};
}
注意点:避免意外暴露私有引用
虽然变量本身不可访问,但如果返回了对私有对象的直接引用,外部仍可能修改它:
- 不要返回私有对象本身(如 return { data: privateObj }),应返回副本或只读视图
- 谨慎使用 this 或箭头函数,确保方法中的 this 指向正确(通常推荐用普通函数或明确绑定)
- 私有函数不能被继承或重写,这本身就是封装的优势


















