JavaScript私有变量与公共属性的核心在于访问控制:私有变量需通过闭包或ES2022+的#语法实现真正封装,公共属性则通过this或prototype明确定义。

JavaScript 中定义私有变量和公共属性,核心在于控制访问权限:私有变量不能被外部直接读写,只能通过内部方法间接操作;公共属性则可自由访问和修改。实现方式随语言演进分三类——传统闭包、ES6+ Symbol 模拟、以及现代标准(ES2022+)的真正私有字段。
用闭包实现真正的私有变量
这是 ES6 之前最可靠的方式,利用函数作用域和闭包捕获变量,外部完全无法触达:
- 在构造函数内用 var/let/const 声明变量,它就成为该次实例的私有状态
- 通过 this.xxx = function() {} 定义特权方法,这些方法能访问闭包内的私有变量
- 原型上的方法(ClassName.prototype.xxx)无法访问这些私有变量
示例:
function Counter(init) {let count = init || 0; // 真正私有,外部不可见
this.increment = () => count++;
this.getCount = () => count;
}
const c = new Counter(5);
c.increment();
console.log(c.getCount()); // 6
console.log(c.count); // undefined —— 无法访问
用 # 号语法声明原生私有字段(推荐)
ES2022 起,类中支持 # 前缀的私有字段和方法,是语言级强制封装:
立即学习“Java免费学习笔记(深入)”;
- #name、#calc() 只能在类定义内部使用
- 试图在类外访问 obj.#name 会立即报 SyntaxError
- 必须在 constructor 或类体内显式声明(如 #name;),否则报错
示例:
class User {#id;
#token;
constructor(id, token) {
this.#id = id;
this.#token = token;
}
getId() { return this.#id; }
#isValid() { return this.#token.length > 10; }
}
const u = new User('u1', 'abc123');
console.log(u.getId()); // 'u1'
console.log(u.#id); // SyntaxError
公共属性与方法的常规定义
公共成员要明确暴露给使用者,分两种典型写法:
- 实例级公共属性:在 constructor 中用 this.prop = value,每个实例独有一份
- 原型级公共方法:挂载到 ClassName.prototype.method,所有实例共享,节省内存
- 避免在构造函数里重复定义函数(如 this.method = function(){}),除非需要闭包捕获私有状态
示例:
function Book(title, author) {this.title = title; // 公共属性,可读可写
this.author = author;
}
Book.prototype.getSummary = function() {
return `${this.title} by ${this.author}`;
};
const b = new Book('JS Guide', 'Lee');
console.log(b.title); // 'JS Guide'
console.log(b.getSummary()); // 'JS Guide by Lee'
不推荐的“伪私有”方式
仅靠命名约定(如 _name)或 Symbol 属性,都不是真正私有:
- _name:只是提示开发者“请勿直接使用”,但 b._name = 'xxx' 完全合法且生效
- Symbol('key'):虽具唯一性,但可通过 Object.getOwnPropertySymbols() 枚举获取,仍可访问
- 它们适合内部文档化或弱约束场景,不适合敏感数据保护



















