要创建一个带有公共方法的JavaScript类,我可以这样做:

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something here
}

Restaurant.prototype.use_restroom = function(){
   // something here
}

这样,我类的用户就可以:

var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();

如何创建一个私有方法,可以由buy_food和use_restroom方法调用,但不能由类的用户外部调用?

换句话说,我希望我的方法实现能够做到:

Restaurant.prototype.use_restroom = function() {
   this.private_stuff();
}

但这是行不通的:

var r = new Restaurant();
r.private_stuff();

如何将private_stuff定义为私有方法,使两者都成立?

我读过Doug Crockford的文章几次,但它似乎不像“私有”方法可以被公共方法调用,而“特权”方法可以被外部调用。


当前回答

2021年这里!

这个polyfill有效地隐藏了你的私有属性和方法,当你试图读取你的私有属性时返回undefined,当你试图执行你的私有方法时返回TypeError,从而有效地使它们对外部都是private,但让你通过使用你的公共方法访问它们。

如果你检查它,你会发现它很容易实现。在大多数情况下,你不需要做任何奇怪的事情,如使用代理对象,下划线函数(_myprivate), getter或setter。都不是。唯一需要做的事情是在构造函数中放置一段类似的代码片段,目的是让您向外界公开您的公共接口。

((self) => ({
      pubProp: self.pubProp,
      // More public properties to export HERE
      // ...
      pubMethod: self.pubMethod.bind(self)
      // More public mehods to export HERE
      // Be sure bind each of them to self!!!
      // ... 
 }))(self);

上面的代码就是魔术发生的地方。它是一个IIFE,返回一个对象,其中只包含您想要公开并绑定到第一次实例化的对象的上下文的属性和方法。

你仍然可以访问你的隐藏属性和方法,但只能通过你的公共方法,就像OOP应该做的那样。 将这部分代码视为module.exports

顺便说一句,这是没有使用最新的ECMAScript 2022 #添加到语言中。

'use strict'; class MyClass { constructor(pubProp) { let self = this; self.pubProp = pubProp; self.privProp = "I'm a private property!"; return ((self) => ({ pubProp: self.pubProp, // More public properties to export HERE // ... pubMethod: self.pubMethod.bind(self) // More public mehods to export HERE // Be sure to bind each of them to self!!! // ... }))(self); } pubMethod() { console.log("I'm a public method!"); console.log(this.pubProp); return this.privMethod(); } privMethod() { console.log("I'm a private method!"); return this.privProp } } const myObj = new MyClass("I'm a public property!"); console.log("***DUMPING MY NEW INSTANCE***"); console.dir(myObj); console.log(""); console.log("***TESTING ACCESS TO PUBLIC PROPERTIES***"); console.log(myObj.pubProp); console.log(""); console.log("***TESTING ACCESS TO PRIVATE PROPERTIES***"); console.log(myObj.privProp); console.log(""); console.log("***TESTING ACCESS TO PUBLIC METHODS***"); console.log("1. pubMethod access pubProp "); console.log("2. pubMethod calls privMethod"); console.log("3. privMethod access privProp"); console.log("") console.log(myObj.pubMethod()); console.log(""); console.log("***TESTING ACCESS TO PRIVATE METHODS***"); console.log(myObj.privMethod());

看看我的主旨

其他回答

Class({  
    Namespace:ABC,  
    Name:"ClassL2",  
    Bases:[ABC.ClassTop],  
    Private:{  
        m_var:2  
    },  
    Protected:{  
        proval:2,  
        fight:Property(function(){  
            this.m_var--;  
            console.log("ClassL2::fight (m_var)" +this.m_var);  
        },[Property.Type.Virtual])  
    },  
    Public:{  
        Fight:function(){  
            console.log("ClassL2::Fight (m_var)"+this.m_var);  
            this.fight();  
        }  
    }  
});  

https://github.com/nooning/JSClass

私有函数不能使用模块模式访问公共变量

我更喜欢将私有数据存储在关联的WeakMap中。这允许你将你的公共方法保留在原型上。对于大量的对象,这似乎是处理这个问题的最有效的方法。

const data = new WeakMap();

function Foo(value) {
    data.set(this, {value});
}

// public method accessing private value
Foo.prototype.accessValue = function() {
    return data.get(this).value;
}

// private 'method' accessing private value
function accessValue(foo) {
    return data.get(foo).value;
}

export {Foo};

模块模式的典范:揭示模块模式

一个非常健壮的模式的简洁的小扩展。

ES2021 / ES12 -私有方法

私有方法名以哈希前缀#开头,并且只能在定义它的类内部访问。

class Restaurant {

  // private method
  #private_stuff() {
    console.log("private stuff");
  }

  // public method
  buy_food() {
    this.#private_stuff();
  }

};

const restaurant = new Restaurant();
restaurant.buy_food(); // "private stuff";
restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function