Javascript 是否存在私有/受保护的原型遗传模式

Javascript 是否存在私有/受保护的原型遗传模式,javascript,inheritance,prototype,private,public,Javascript,Inheritance,Prototype,Private,Public,Javascript对象中私有/受保护的大多数方法的问题是,它们使用闭包。这样,它们必须在构造函数中定义,所有想要访问它们的公共方法也必须在构造函数中定义 这使得两件事变得不可能: 共享公共方法实例的对象实例。对象的每个实例都必须有其自己的每个方法的实例,这些方法可以访问私有成员 儿童能够从其父母处访问和重用受保护的方法 有没有办法解决这两个问题,这样私有方法就可以在所有实例中共享,同时子对象也可以重用受父对象保护的方法 另外,至少在ECMA5级别上,对浏览器的支持也不错。虽然这可能不是一个

Javascript对象中私有/受保护的大多数方法的问题是,它们使用闭包。这样,它们必须在构造函数中定义,所有想要访问它们的公共方法也必须在构造函数中定义

这使得两件事变得不可能:

  • 共享公共方法实例的对象实例。对象的每个实例都必须有其自己的每个方法的实例,这些方法可以访问私有成员
  • 儿童能够从其父母处访问和重用受保护的方法
有没有办法解决这两个问题,这样私有方法就可以在所有实例中共享,同时子对象也可以重用受父对象保护的方法


另外,至少在ECMA5级别上,对浏览器的支持也不错。

虽然这可能不是一个完美而优雅的解决方案,但我找到了解决上述问题的方法

建造师 首先看一下我们的构造函数,以及一些原型方法

函数构造函数(args){
this.args=args;
this.private=“来自foo的小写机密”;
这是一个出口={
publicMethod:this.publicMethod.bind(this)
};
}
FooConstructor.prototype.privateMethod=函数(){
把这个归还给私人;
}
FooConstructor.prototype.publicMethod=函数(){
返回此.privateMethod().toUpperCase();
}
不是对象
这个。导出
。在这里,我们将储存所有应该公开的东西

重要的是,我们不直接调用构造函数,而是使用Factorymethod,它获取对象的实例,然后只返回
导出
对象

function getInstanceFoo(args) {
    return new FooConstructor(args).exports;
}
现在,如果我们想要一个Foo的实例,我们只需要这样做

var fooInstance = getInstanceFoo("fooArg");
从这个实例中,我们只能访问放入
exports
对象的内容

fooInstance.publicMethod(); // "LOWER CASE SECRET FROM FOO"
fooInstance.private;        // undefined
fooInstance.privateMethod;  // undefined 
                            // calling it would give you: 
                            // Uncaught TypeError: fooInstance.privateMethod is not a function
子构造函数 好的是,现在我们的工厂只输出我们想要公开的东西,但我们仍然有一个可以访问的构造函数。因此,对于一个孩子,我们可以做到:

function BarConstructor(args) {
    // this will just copy all the exported methods from Foo
    FooConstructor.call(this, args);

    // overwrite stuff we don’t want from the parents constructor
    this.privateMember = "lower case secret from bar";

    // add publics that should be exported for the child
    this.exports.newPublicMethod = this.newPublicMethod.bind(this);
}

BarConstructor.prototype = new FooConstructor();

BarConstructor.prototype.newPublicMethod = function() {
    return "My args: " + this.args;
}

function getInstanceBar(args) {
    return new BarConstructor(args).exports;
}

var barInstance = getInstanceBar("barArg");

barInstance.publicMethod();    // "LOWER CASE SECRET FROM BAR"
barInstance.newPublicMethod(); // "My args: barArg"
barInstance.private;           // undefined
总结 就这样。这就是我们想要的。 您可以在这里试用:

//构造函数------------------------------------------
函数构造函数(args){
this.args=args;
this.privatember=“来自foo的小写机密”;
这是一个出口={
publicMethod:this.publicMethod.bind(this)
};
}
FooConstructor.prototype.privateMethod=函数(){
返回此。privateMember;
}
FooConstructor.prototype.publicMethod=函数(){
返回此.privateMethod().toUpperCase();
}
//食品厂
函数getInstanceFo(args){
返回新的FooConstructor(args);
}
//酒吧建造师------------------------------------------
函数构造函数(args){
//这将只是从Foo复制所有导出的方法
FooConstructor.call(this,args);
this.privatember=“来自bar的小写机密”;
this.exports.newPublicMethod=this.newPublicMethod.bind(this);
}
BarConstructor.prototype=new FooConstructor();
BarConstructor.prototype.newPublicMethod=函数(){
返回“我的args:+this.args;
}
//酒吧
函数getInstanceBar(args){
返回新的BarConstructor(args);
}
//获取实例------------------------------------------
var fooInstance=getInstancefo(“fooArg”),
barInstance=getInstanceBar(“barArg”);
log(“fooInstance.publicMethod():”+fooInstance.publicMethod());
log(“fooInstance.private:+fooInstance.private”);
log(“fooInstance.privateMethod:+fooInstance.privateMethod”);
log(“barInstance.publicMethod():”+barInstance.publicMethod());
log(“barInstance.newPublicMethod():”+barInstance.newPublicMethod());

console.log(“barInstance.private:+barInstance.private”)
子级不能使用或访问父级的私有方法,只能访问受保护的方法。
WeakMap
s可用于解决大多数与私有数据相关的问题。我相信这之前已经被问过/讨论过了。OTOH,为什么要在JavaScript对象上强制一个不是为其设计的模型呢?@ssube可能用词不对。但是,如果我有一个函数,它可以处理一些复杂的事情,并且希望在一个孩子身上重用它,而这个方法不是公共的,我该如何调用它呢?或者我为什么不想这么做?也许我在推理我遗漏了什么的时候有一些错误。@FelixKling-WeakMaps听起来很麻烦。而且浏览器支持也不是很好。但我会调查的。你需要多隐私?使用符号可以防止意外使用私有方法,并且不需要像下面这样在构造函数中创建新函数。