全部 / 前端 / 技术 · 2022年7月2日 0

51 – JS 中的类:Public、Private 和 Protected

原文地址:https://dev.to/bhagatparwinder/classes-in-js-public-private-and-protected-1lok

即使 ES6 中引入了 class 关键字很好的模拟了类的行为以及使我们可以进行面向对象编程,但 JavaScript 中的类缺失了创建公共、私有和保护成员的能力。

若你之前使用过其他面向对象的编程语言,肯定知道内部和外部接口的重要性。内部接口引用的方法和属性只能在类的内部获取。相反,外部接口的方法和属性可以在内外部都可获取。

主要有三个关键字在起作用:public、protected 和 private。

  1. public:类的所有成员都可以被类的实例获取。
  2. private:类成员只能在类中被访问。
  3. protected:类成员在类以及子类中可以被访问

在 JavaScript 中 protected 关键字是最难模拟的。

public

publick 是 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.