javascript中定义私有方法说明(private method)


在JavaScript中,直到ES2020(ECMAScript 2020)之前,语言标准本身并不直接支持类的私有方法和属性。但是,从ES2022(目前处于草案阶段,但预期将很快被正式采纳)开始,将引入类字段(包括私有字段)的语法。

不过,在ES2022之前,开发者们通常使用几种模式来模拟私有方法和属性。这里我将说明如何使用`WeakMap`来模拟类的私有方法。


// 使用WeakMap来模拟类的私有方法
class MyClass {
    constructor(name) {
        // WeakMap的键是对象,值是与之关联的私有数据
        // 这里我们将类的实例作为键,私有方法作为值
        if (!MyClass._privateMethods) {
            MyClass._privateMethods = new WeakMap();
        }

        // 初始化私有方法
        MyClass._privateMethods.set(this, {
            privateMethod: function() {
                console.log(`This is a private method. Name: ${name}`);
            }
        });
    }

    // 公有方法,可以调用私有方法
    publicMethod() {
        const privateMethods = MyClass._privateMethods.get(this);
        if (privateMethods) {
            privateMethods.privateMethod();
        }
    }
}

// 使用示例
const instance = new MyClass('Alice');
instance.publicMethod(); // 输出: This is a private method. Name: Alice

// 注意:直接访问私有方法是不可行的
// console.log(instance.privateMethod); // 这将导致undefined,因为privateMethod不是实例的属性

然而,请注意,上面的方法并不是真正的私有方法,因为JavaScript的动态性允许用户通过不同的方式(如上述示例中的直接访问)来绕过这种封装。但它是一种在ES2022之前广泛使用的模式,用于在JavaScript中模拟私有方法的行为。

从ES2022开始,你可以直接在类定义中使用`#`前缀来标记私有方法和属性,如下所示:


class MyClass {
    #privateMethod() {
        console.log('This is a true private method.');
    }

    publicMethod() {
        this.#privateMethod(); // 正确调用私有方法
    }
}

const instance = new MyClass();
instance.publicMethod(); // 输出: This is a true private method.
// instance.#privateMethod(); // 这将引发语法错误,因为私有成员不能从类外部访问

使用`#`前缀定义的私有方法和属性是真正的私有成员,它们不能在类的外部被直接访问或修改。