在Javascript中访问私有成员的更好方法

在Javascript中访问私有成员的更好方法,javascript,prototype,Javascript,Prototype,在阅读了一些Javascript之后,我改变了从 var Some_Class = function() { this.public_method = function() { }; (function() { // constructor }).call(this) } 到 虽然我知道这是一个很好的实践,但我不再被允许从公共方法访问私有方法 var Some_Class = function() { var private_member

在阅读了一些Javascript之后,我改变了从

var Some_Class = function() {
    this.public_method = function() {
    };
    (function() {
        // constructor
    }).call(this)
}

虽然我知道这是一个很好的实践,但我不再被允许从公共方法访问私有方法

var Some_Class = function() {
    var private_member = 'whatever';

    (function() {
        // constructor
    }).call(this)
}
Some_Class.prototype.public_method = function() {
    return private_member; // not possible
};
在阅读了一篇文章(闭包创建的构造函数)之后,我得出了这个结论

var Some_Class = function() {
    var private_member = 'whatever',

    private_method = function(_some_value) {
        // private method implementation
    };

    if(!arguments.callee.prototype.public_method) {
        arguments.callee.prototype.public_method = function() {
            private_method.call(this, private_method);
        };
    }

    (function() {
        // constructor
    }).call(this)
}

然而,这样做的缺点是什么?!或者,如果我想在公共方法中访问,有没有更好的方法来实现这一点?

使用函数作用域变量和闭包来模拟私有变量/函数是javascript社区中公认的习惯用法。如果变量确实是私有的,我认为这种方法没有缺点(尽管有人声称在某些浏览器/主机上执行代码必须注意创建了多少闭包)

在您的示例中,私有_方法(及其环境)在所有对象之间共享,因为您的公共_方法闭包仅在第一次构造对象时创建(并绑定到设置所创建对象的内部原型链的构造函数的prototype属性)-因此使用的private_方法只是第一次创建的方法

下面是一些示例代码,有助于说明发生了什么:

var global = 1; var Some_Class = function() { var private_method = 'whatever'; var now = ++global; print("outer now: " + now ); private_method = function(_some_value) { // private method implementation print("inner now: " + now); }; if(!arguments.callee.prototype.public_method) { arguments.callee.prototype.public_method = function() { private_method.call(this, private_method); }; } (function() { // constructor }).call(this) } new Some_Class().public_method(); // outer now: 2, inner now: 2 new Some_Class().public_method(); // outer now: 3, inner now: 2 new Some_Class().public_method(); // outer now: 4, inner now: 2 var全局=1; var Some_Class=函数(){ var private_method='whatever'; var now=++全局; 打印(“外部现在:+now”); 私有方法=函数(\u某些值){ //私有方法实现 打印(“内部现在:+now”); }; if(!arguments.callee.prototype.public_方法){ arguments.callee.prototype.public_方法=函数(){ 调用(这个,private\u方法); }; } (功能(){ //建造师 }).打电话(这个) } 新的Some_类().public_方法();//外部现在:2,内部现在:2 新的Some_类().public_方法();//外部现在:3,内部现在:2 新的Some_类().public_方法();//外部现在:4,内部现在:2 你确定这就是你想要的吗

如果您的private_方法不需要引用封闭对象的状态,那么我认为您这样做没有什么好处

我通常会做以下操作(如果我必须使用“新建”来创建对象):

function MyClass() { var private_var = 1; function private_func() { } this.public_func = function() { // do something private_func(); } this.public_var = 10; } var myObj = new MyClass(); 函数MyClass(){ var-private_var=1; 函数private_func() { } this.public_func=函数() { //做点什么 private_func(); } 这个公共变量=10; } var myObj=new MyClass(); 这种方法的缺点是,每次通过“new”构造对象时,都会重新创建所有闭包。但是,除非我的分析器告诉我这个设计选择需要优化,否则我更喜欢它的简单和清晰

此外,我也看不到您的代码中执行以下操作的好处:

(function() { }).call(this); // call the constructor (函数(){})。调用(this);//调用构造函数
为什么要在构造函数中创建一个单独的作用域?

我的答案是否定的:JavaScript中没有内置的
private
访问,但这没关系,因为。以下是我如何在代码中创建
私有成员的方法:

function Some_Class() {
    this._private_member = 'whatever';
}

Some_Class.prototype._private_method = function() {
};
这就够了。当
private
的唯一真正目的是保护自己不受。。。你自己


(我说我自己花了很多时间玩弄闭包和原型的每一种排列,就像你一样,最后说“去他妈的,这不值得。”)

如果你还没有这样做,请看看这个,它允许你从公共函数中访问私有方法和变量,等等。

与原型一起工作,而不仅仅是单例。问题是,当到了创建子类的时候,我的子类无法访问privates

响应John Kugelman的说法:不可能用javascript创建私有成员。接受它。即使您创建这样的机柜:

function SomeClass() {

   var _private = 0;
   this.public_acessor = function() {return _private};
}
任何用户仍然可以写入:

SomeClass._not_private_anymore = 1;
SomeClass.public_acessor = function () {return this._not_private_anymore}; 

最后,您不能相信任何公共成员与您声明的成员相同。如果有人想破坏你的密码,他会的!其他用户不会仅仅因为代码有用就破坏您的代码。

我同意。在不支持的语言中强制使用虚假的私有访问通常意味着你要这样做。@Triptych-虽然我通常同意,如果你必须与一种设计良好的语言作斗争来做你想做的事情,那么你应该真正重新考虑你的设计。但是,在这种情况下,通过函数作用域变量和闭包模拟私有访问被许多成熟且经验丰富的javascript程序员认可为一种自然的javascript习惯用法。+1一个副作用是所有古怪的闭包方案往往会破坏许多IDE代码助手。感谢您澄清这一点,对于第二个问题。。。我想这可能是因为我对对象模型还不是很熟悉,我想让我的代码类似于php/java/其他OOP编程语言中的OOP代码:D我以前读过,只是出于某种原因,我不太喜欢单例模式,并希望找到另一种方法……即使是Java中的子类也无法访问它们的
超级
私有类。
SomeClass._not_private_anymore = 1;
SomeClass.public_acessor = function () {return this._not_private_anymore};