JavaScript 类中 Public、Private 和 Protected 成员的模拟与实现

作者:拾光时间:2026-10-25 19:00:57浏览:404

本文深入解析 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()); // Parwinder

Private

在 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 defined

car 和 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 内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章