可能有很多人试图在JavaScript中实现封装。我知道的两种方法是:
我想更常见:
var myClass(){
var prv //and all private stuff here
//and we don't use protoype, everything is created inside scope
return {publicFunc:sth};
}
和第二个:
var myClass2(){
var prv={private stuff here}
Object.defineProperty(this,'prv',{value:prv})
return {publicFunc:this.someFunc.bind(this)};
}
myClass2.prototype={
get prv(){throw 'class must be created using new keyword'},
someFunc:function(){
console.log(this.prv);
}
}
Object.freeze(myClass)
Object.freeze(myClass.prototype)
所以,第二种选择对我来说更方便(特别是在我的情况下,因为它在视觉上将结构与工作流分开),问题是 - 在这种情况下是否有任何严重的缺点/泄漏?我知道它允许外部代码通过
访问someFunc
的参数
myClass.protoype.someFunc.arguments
但仅限于执行粗略的回调(在调用者链内同步)。使用setTimeout(cb,0)调用它们可以打破链并禁止获取参数以及同步返回值。至少据我所知。
我错过了什么吗?这很重要,因为外部的,不受信任的用户提供的代码将使用代码。
答案 0 :(得分:4)
我喜欢将我的原型包装在一个返回对象的模块中,这样你就可以将模块的范围用于任何私有变量,保护你的对象的消费者不会意外地搞乱你的私有属性。
var MyObject = (function (dependency) {
// private (static) variables
var priv1, priv2;
// constructor
var module = function () {
// ...
};
// public interfaces
module.prototype.publicInterface1 = function () {
};
module.prototype.publicInterface2 = function () {
};
// return the object definition
return module;
})(dependency);
然后在其他文件中,您可以像平常一样使用它:
obj = new MyObject();
你的对象的任何“保护”对于JavaScript imo来说都有点过分。如果有人想扩展你的对象,那么他们可能知道他们正在做什么,你应该让他们!
正如redbmk指出,如果您需要私有实例变量,您可以使用带有该对象的唯一标识符的地图作为密钥。
答案 1 :(得分:1)
嗯,它并没有真正使用原型。这里没有理由“封装”任何东西,因为原型方法只能使用公共属性 - 就像你的不受信任的代码可以访问它们一样。一个简单的所以,第二个选项对我来说更方便(特别是在我的情况下,因为它在视觉上将构造与工作流分开),问题是 - 在这种情况下是否有任何严重的缺点/泄漏?
function myClass2(){
var prv = // private stuff here
Object.defineProperty(this, 'prv', {value:prv})
// optionally bind the publicFunc if you need to
}
myClass2.prototype.publicFunc = function(){
console.log(this.prv);
};
应该足够了。或者您使用工厂模式,没有任何原型:
function myClass2(){
var prv = // private stuff here
return {
prv: prv,
publicFunc: function(){
console.log(this.prv); // or even just `prv`?
}
};
}
我知道它允许外部代码访问someFunc的参数 myClass.protoype.someFunc.arguments
只需使用严格模式,就不允许使用此“功能”。
这很重要,因为外部的,不受信任的用户提供的代码将使用代码。
如果代码在同一环境中运行,他们将始终获取您的秘密。总是。您可能想要尝试WebWorkers,但请注意它们仍然是CORS特权。
答案 2 :(得分:0)
使用不能正确支持私人,受保护和公共类成员的语言强制执行封装,我说" Meh。"
我喜欢Foo.prototype = { ... };
语法的清晰度。公开方法还允许您对"类"中的所有方法进行单元测试。最重要的是,我只是从安全的角度来看,不相信JavaScript。始终在保护系统的服务器上采取安全措施。
轻松编程和测试"和#34;清洁代码。"使编写和维护变得容易,因此无论您感觉更容易编写和维护都是答案。