函数表达式通过闭包与作用域隔离实现私有变量保护,包括iife封装单例、工厂函数创建多实例、weakmap配合class存储私有数据三种方式,本质是运行时作用域控制而非语法级限制。

函数表达式实现私有变量保护,核心是闭包 + 作用域隔离。它不依赖语法糖或新特性,而是利用 JavaScript 函数执行时创建独立作用域的天然机制,让变量“藏在内部”,只通过返回的方法间接访问。
用立即执行函数表达式(IIFE)封装单个私有状态
把变量声明在函数体内,仅暴露操作它的方法,外部无法直接读写该变量。
- 变量定义在 IIFE 内部,不属于任何对象属性,也不挂载到全局
- 返回的对象方法因闭包持有对外部变量的引用,可安全读写
- 每次调用 IIFE 都生成全新作用域,适合一次性模块或单例
示例:
const counter = (function() {
let count = 0; // 真正的私有变量
return {
increment: () => ++count,
value: () => count
};
})();
<p>counter.increment();
console.log(counter.value()); // 1
console.log(counter.count); // undefined —— 不可访问
</p>
用工厂函数配合函数表达式创建多个独立实例
把 IIFE 换成普通函数,每次调用都生成新闭包,每个实例拥有自己的一份私有数据。
- 私有变量与实例绑定,不同实例间完全隔离
- 方法用函数表达式定义(而非原型上),确保能捕获当前闭包中的变量
- 代价是每个实例都复制一份函数,但换来的是强封装性
示例:
function createUser(name) {
const _name = name; // 私有字段
let _age = 25;
<p>return {
getName: () => _name,
setAge: (age) => { _age = age; },
getAge: () => _age
};
}</p><p>const user1 = createUser('Alice');
const user2 = createUser('Bob');
user1.setAge(30);
console.log(user2.getAge()); // 25 —— 不受影响
</p>
结合 WeakMap 实现类中真正的实例级私有存储
当需要 class 语法又想保持私有性时,可在构造函数里用函数表达式 + WeakMap 存储私有数据。
- WeakMap 以 this 为键,避免属性名暴露,也防止被枚举或反射获取
- 所有方法都是普通函数,但通过闭包或 WeakMap 访问私有数据
- 比 # 字段兼容性更好,且内存更可控(WeakMap 自动随实例回收)
示例:
const privateData = new WeakMap();
<p>class BankAccount {
constructor(balance) {
privateData.set(this, { balance }); // 私有存储
}</p><p>deposit(amount) {
const data = privateData.get(this);
data.balance += amount;
}</p><p>getBalance() {
return privateData.get(this).balance;
}
}
</p>
关键提醒:这不是“绝对私有”,而是运行时保护
函数表达式实现的私有,本质是靠作用域和引用控制,不是语言级访问限制:
- 没有语法报错(不像 #field 会抛 TypeError),但变量确实不可直接访问
- 调试时可通过闭包面板查看,但生产环境代码压缩后基本不可见
- 只要不返回变量引用、不把它挂到可访问对象上,就守住了边界
不复杂但容易忽略。











