本文深入解析 JavaScript 中类的可见性控制。尽管 ES6 class 引入了类语法,但原生缺乏私有和保护成员支持。文章详细阐述了 Public 的默认行为,介绍了利用闭包和 ES2019 引入的 # 符号实现 Private 成员的方法,并探讨了通过仅暴露 getter 来模拟 Protected 成员的技巧,帮助开发者更好地进行代码封装。
前言
原文地址:dev.to/bhagatparwi…
尽管 ES6 引入了 class 关键字,较好地模拟了类的行为并支持面向对象编程,但 JavaScript 的类机制在创建公共、私有和保护成员方面仍存在缺失。
如果你熟悉其他面向对象编程语言,就会明白内部接口与外部接口的重要性。内部接口包含的方法和属性仅在类内部可见,而外部接口的方法和属性则可以在类内外被访问。
主要涉及三个可见性关键字:public、protected 和 private。
- public:类的实例可以访问该类的所有成员。
- private:类成员仅在类内部可被访问。
- protected:类成员在类本身及其子类中均可被访问。
在 JavaScript 中,模拟 protected 关键字是最具挑战性的部分。
Public
public 是 JavaScript 中的默认状态。如果属性或方法可以从对象实例上获取,那么它自然也是公开的。
const myObject = {
name: "Parwinder",
sayMyName: function () {
return this.name;
}
}
console.log(myObject.name); // Parwinder
console.log(myObject.sayMyName()); // Parwinder在上面的示例中,获取属性和方法均无问题。如果你更倾向于使用类语法,可以参考以下写法:
class ObjectCreator {
name;
constructor(name) {
this.name = name;
}
sayMyName() {
return this.name;
}
}
const myObject = new ObjectCreator("Parwinder");
console.log(myObject.name); // Parwinder
console.log(myObject.sayMyName()); // ParwinderPrivate
在 JavaScript 中,有多种方式可以创建私有变量,第一种方法是利用闭包:
function carMonitor() {
var speed = 0;
return {
accelerate: function () {
return speed++;
}
}
}
var car = new carMonitor();
var redCar = new carMonitor()
console.log(car.accelerate()); // 0
console.log(car.accelerate()); // 1
console.log(redCar.accelerate()); // 0
console.log(redCar.accelerate()); // 1
console.log(car.accelerate()); // 2
console.log(redCar.accelerate()); // 2
console.log(speed); // speed is not definedcar 和 redCar 各自维护独立的 speed 变量,外部无法直接访问。在构造函数或类中,我们强制用户通过特定方法来获取属性,而非直接读写,从而实现代码封装。
第二种方法则是使用 # 符号。
class ObjectCreator {
#meaningOfLife;
constructor(name) {
this.#meaningOfLife = 42;
}
returnMeaningOfLife() {
return this.#meaningOfLife;
}
#returnAMessage() {
return "You will do great things in life";
}
}
const myObject = new ObjectCreator("Parwinder");
console.log(myObject.returnMeaningOfLife()); // 42
console.log(myObject["#meaningOfLife"]); // undefined
console.log(myObject.#meaningOfLife); // SyntaxError
console.log(myObject.#returnAMessage); // SyntaxError这种方法从语言层面强制实现了代码封装,外部直接访问 # 引用的字段会引发错误。public 和 private 字段共存时不会冲突,同一类中既可以存在私有的 #meaningOfLife,也可以存在公共的 meaningOfLife。
在类中使用 # 符号声明私有成员的特性是在 ES2019(即 ES10)中引入的。
Protected
正如前文所述,在 JavaScript 中实现 protected 是三者中最难的。我能想到的实现途径是通过仅提供 getter 而不提供 setter 的方法来实现受保护访问。
如果你有其他实现 protected 的方法,欢迎分享!
class NameGenerator {
_name;
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
}
let nameGenerator = new NameGenerator("John");
console.log(`My name is ${nameGenerator.name}`); // My name is John
nameGenerator.name = "Jane"; // Cannot assign to 'name' because it is a read-only property.至此,关于 JS 中类的 Public、Private 和 Protected 详解文章介绍完毕。更多相关 JS Public、Private、Protected 内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!