JavaScript私有字段以#开头,实现类内部状态的真正私有化,与下划线约定不同,其私有性由语言强制保证,避免外部访问,支持私有方法和访问器,提升封装性与代码健壮性。

JavaScript的私有字段提供了一种在类内部封装状态的强大机制,它们以
#
在我看来,JavaScript私有字段的引入,终于给开发者提供了一个官方的、语言层面的封装方案,这解决了长期以来我们对类内部状态保护的痛点。过去,我们依赖下划线约定(
_propertyName
#
SyntaxError
这种机制的强大之处在于其强制性。它不是一个建议,而是语言规范。这意味着,当你定义了一个
#count
Counter
myCounter.#count
class Counter {
#count = 0; // 私有字段
constructor(initialCount = 0) {
if (initialCount < 0) {
throw new Error("Initial count cannot be negative.");
}
this.#count = initialCount;
}
increment() {
this.#count++;
console.log(`Count: ${this.#count}`);
}
decrement() {
if (this.#count > 0) {
this.#count--;
console.log(`Count: ${this.#count}`);
} else {
console.log("Count cannot go below zero.");
}
}
get currentCount() {
return this.#count; // 可以在类内部访问私有字段
}
}
const myCounter = new Counter(5);
myCounter.increment(); // Count: 6
myCounter.decrement(); // Count: 5
console.log(myCounter.currentCount); // 5
// 尝试从外部访问私有字段会报错
// console.log(myCounter.#count); // SyntaxError: Private field '#count' must be declared in an enclosing class这真的是一个核心问题,也是私有字段之所以被引入的关键原因。在我看来,两者之间的区别,就像是“口头约定”和“法律条款”一样。
下划线约定(_propertyName
myObject._privateProperty
私有字段(#propertyName
#property
SyntaxError
TypeError
举个例子,假设我们有一个用户类:
// 使用下划线约定
class UserOld {
constructor(name, password) {
this.name = name;
this._password = password; // 约定为私有
}
authenticate(inputPassword) {
return this._password === inputPassword;
}
}
const oldUser = new UserOld("Alice", "secret123");
console.log(oldUser._password); // 'secret123' - 可以直接访问,甚至修改 oldUser._password = "newPassword"
// 使用私有字段
class UserNew {
#password; // 真正的私有字段
constructor(name, password) {
this.name = name;
this.#password = password;
}
authenticate(inputPassword) {
return this.#password === inputPassword;
}
}
const newUser = new UserNew("Bob", "secure456");
// console.log(newUser.#password); // SyntaxError: Private field '#password' must be declared in an enclosing class显然,私有字段提供了更强的封装性和安全性,是实现健壮、可维护的面向对象设计的更优选择。
私有字段的
#
私有方法: 当你有一些辅助函数,它们只在类的其他方法内部被调用,并且不应该成为类公共API的一部分时,就可以将它们定义为私有方法。这使得类的公共接口保持简洁,只暴露必要的功能。
class DataProcessor {
#data = [];
constructor(initialData) {
this.#data = initialData;
}
#validate(value) { // 私有方法
if (typeof value !== 'number') {
throw new Error("Data must be a number.");
}
return true;
}
#calculateAverage() { // 另一个私有方法
if (this.#data.length === 0) return 0;
const sum = this.#data.reduce((acc, num) => acc + num, 0);
return sum / this.#data.length;
}
addData(value) {
this.#validate(value); // 在公共方法中调用私有方法
this.#data.push(value);
}
getAverage() {
return this.#calculateAverage(); // 在公共方法中调用私有方法
}
}
const processor = new DataProcessor([10, 20, 30]);
processor.addData(40);
console.log(processor.getAverage()); // 25
// processor.#validate(50); // SyntaxError
// processor.#calculateAverage(); // SyntaxError私有访问器(Getter/Setter): 有时,你可能需要一个内部的计算属性,或者一个需要在设置时进行复杂验证的属性,但你又不希望这些访问器直接暴露为公共接口。这时,私有访问器就派上用场了。它们允许你在类内部以属性的方式访问或修改私有字段,同时保持其私有性。
class TemperatureSensor {
#celsius = 0;
constructor(initialCelsius) {
this.#setCelsius(initialCelsius); // 通过私有setter初始化
}
#setCelsius(value) { // 私有setter
if (value < -273.15) { // 绝对零度检查
throw new Error("Temperature cannot be below absolute zero.");
}
this.#celsius = value;
}
#getCelsius() { // 私有getter
return this.#celsius;
}
getFahrenheit() {
return (this.#getCelsius() * 9 / 5) + 32; // 使用私有getter
}
setTemperature(celsius) {
this.#setCelsius(celsius); // 通过公共方法调用私有setter
}
}
const sensor = new TemperatureSensor(25);
console.log(sensor.getFahrenheit()); // 77
sensor.setTemperature(100);
console.log(sensor.getFahrenheit()); // 212
// sensor.#setCelsius(50); // SyntaxError
// sensor.#getCelsius(); // SyntaxError通过私有方法和私有访问器,我们可以构建出更内聚、更清晰的类结构,将内部实现细节完全隐藏起来,只对外提供一个简洁、稳定的API接口。
防封域名方法千千种,我们只做最简单且有用的这一种。微信域名防封是指通过技术手段来实现预付措施,一切说自己完全可以防封的那都是不可能的,一切说什么免死域名不会死的那也是吹牛逼的。我们正在做的是让我们的推广域名寿命更长一点,成本更低一点,效果更好一点。本源码采用 ASP+ACCESS 搭建,由于要用到二级域名,所以需要使用独享云虚机或者云服务器,不支持虚拟主机使用,不支持本地测试。目前这是免费测试版,
0
虽然私有字段是JavaScript中一个非常受欢迎的特性,但作为开发者,我们总得考虑它的实际落地和一些使用上的细节。
兼容性: 私有字段是ECMAScript 2022(ES13)标准的一部分,这意味着它是一个相对较新的特性。
使用注意事项:
实例绑定,而非原型绑定:私有字段是绑定到类的每个实例上的,而不是绑定到类的原型上。这意味着每个实例都会有自己独立的私有字段副本。这与公共方法通常定义在原型上以节省内存的做法不同。
继承性:这是一个重要的点。私有字段是不会被子类继承的。子类无法直接访问或修改父类的私有字段。如果子类需要与父类的私有状态交互,父类必须提供公共或受保护的方法来间接操作这些私有字段。这确保了父类的封装性不会因为继承而泄露。
class Parent {
#privateData = "I am private in Parent";
getPrivateData() {
return this.#privateData;
}
}
class Child extends Parent {
accessParentPrivate() {
// return this.#privateData; // SyntaxError: Private field '#privateData' must be declared in an enclosing class
return this.getPrivateData(); // 正确做法:通过公共方法访问
}
}
const child = new Child();
console.log(child.accessParentPrivate()); // "I am private in Parent"in
in
class MyClass {
#myPrivateField = 10;
}
const instance = new MyClass();
console.log(#myPrivateField in instance); // true
const anotherObject = {};
console.log(#myPrivateField in anotherObject); // false序列化:私有字段在对象被序列化(例如,使用
JSON.stringify()
命名冲突:由于
#
总的来说,私有字段的引入是JavaScript在面向对象编程方面迈出的重要一步,它提供了更强的封装能力,让开发者能够构建出更健壮、更易于维护的类。理解其兼容性、继承行为以及
in
以上就是什么是JS的私有字段?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号