在Javascript的prototypical inheritance model上读了一下后,我改变了构建类的风格
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(Closure创建的构造函数)后,我就出来了
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,还是有更好的方法吗?
答案 0 :(得分:11)
我的回答是无答案:JavaScript中没有内置的private
访问权限,但这可以,因为YAGNI。以下是我在代码中创建private
成员的方法:
function Some_Class() {
this._private_member = 'whatever';
}
Some_Class.prototype._private_method = function() {
};
这很好。当private
的唯一真正目的是保护自己免受......自己时,跳过篮球并不值得。
(我说这花了很多时间自己玩弄关闭和原型制作的每一个排列,就像你一样,最后说“搞砸它,它不值得”。)
答案 1 :(得分:10)
使用函数范围变量和闭包来模拟私有变量/函数是javascript社区中一个成熟的习惯用法。如果该变量确实是私有的,我认为这种方法没有任何缺点(尽管有些人声称某些浏览器/主机上的高性能代码必须注意创建多少个闭包)。
在您的示例中,private_method(及其环境)在所有对象之间共享 - 因为您的public_method闭包仅在第一次构造对象时创建(并绑定到构造函数的prototype属性,该属性设置创建的对象的内部原型链) - 所以使用的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不需要引用封闭对象的状态,那么我认为按照你的方式做事情没什么好处。
我通常做的事情(如果我必须使用'new'来创建我的对象)如下:
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();
这种方法的缺点是每次通过'new'构造对象时,都会重新创建所有闭包。但除非我的探查器告诉我这个设计选择需要优化,否则我更喜欢它的简洁性和清晰度。
此外,我也没有看到您的代码中有以下好处:
(function() { }).call(this); // call the constructor
为什么要在构造函数中创建单独的作用域?
答案 2 :(得分:1)
如果您还没有这样做,请查看此JavaScript Module Pattern,它允许您从公共函数中访问私有方法和变量等。
答案 3 :(得分: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};
最后,您不能相信任何公共成员与您声明的成员相同。如果有人要破坏你的代码,他会!另一个用户不会因为它有用而破坏你的代码。
答案 4 :(得分:0)
使用原型,而不仅仅是单身。问题是,当是子类的时候,我的子类无法访问私有