2009-06-25 55 views
7

阅读JavaScript的prototypical inheritance model了一下后,我改变我的构造一类的风格从更好的方式来访问私有成员的Javascript

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

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

虽然我明白,这是一个良好的做法,但我不允许从公共方法访问私人方法

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

    (function() { 
     // constructor 
    }).call(this) 
} 
Some_Class.prototype.public_method = function() { 
    return private_member; // not possible 
}; 

通过文章here(封闭创建构造函数)看完后,然后我来到了这个

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) 
} 

然而,什么是这样做的缺点?或者如果我想在公共方法中访问private member,是否有更好的方法?

回答

10

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

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

下面是一些示例代码,将有助于说明这是怎么回事:

 
    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 

你确定这是你想要的吗?

如果你的private_method不需要引用封闭对象的状态,那么我看到你按照自己的方式做事情没有什么好处。

我最常做的(如果我必须使用“新”创建我的对象)如下:

 
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(); 

对这个缺点的方法是,每次通过构造对象“新”你重新创建所有关闭。但除非我的配置文件告诉我这个设计选择需要优化,我更喜欢它的简洁和清晰。

我也没有看到好处在你做下面的代码之一:

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

你为什么要建立在你的构造一个单独的范围是什么?

+0

感谢您澄清,第二个问题...我想这可能是因为我仍然不太熟悉对象模型,并希望使我的代码类似于OOP代码在php/java/other OOP编程语言 – Jeffrey04 2009-06-25 06:32:40

11

我的回答是不回答:JavaScript中没有内置的private访问权限,但没关系,因为YAGNI。以下是我在做我的代码private成员:

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

Some_Class.prototype._private_method = function() { 
}; 

这是不够好。当private的唯一真正目的是为了保护自己... ...自己时,跳过篮球真的不值得。

(我这样说是花了很多时间自己带密封盖和原型设计的每一个排列玩耍,就像你的,最后说:“拧它,它不值得”。)

+0

我同意。在不支持它的语言中强制伪造私人访问通常意味着UR会发生改变。 – Triptych 2009-06-25 03:48:25

+0

@Triptych - 虽然我一般都认为,如果你必须打好设计好的语言来做你想做的事情,那么你应该重新考虑你的设计。但是,在这种情况下,通过函数作用域变量和闭包来模拟私人访​​问被许多熟知并且经验丰富的JavaScript程序员认可为自然的javascript成语。 – 2009-06-25 04:29:54

+0

+1一个副作用是所有古怪的封闭计划倾向于打破许多IDEs代码助手 – 2012-04-02 22:26:27

1

如果您还没有这样做已经看到了这个JavaScript Module Pattern,它允许您访问公共职能范围内的私人方法和变量等。

0

与原型,而不仅仅是单身。问题是,当是子类化的时候,我的子类无法访问私有成员

1

回应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}; 

最后,你不能相信任何公共成员是你声明的一样。如果有人打破你的代码,他会!另一个用户不会因为它的用处而破坏你的代码。