我使用模块模式创建一个类cuz我需要一些私有成员和函数。问题是我无法为一个模块创建多个实例。如果我创建一个新实例,它将替换我之前创建的所有实例。
这是代码。
var MyObj = (function() {
var myVar;
function MyObj(arg) {
myVar = arg;
}
MyObj.prototype.print = function() {
console.log(myVar);
};
return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2
这是我的问题: 1.这是否意味着如果我想使用这种模式,我不能为一个类创建多个实例? 2.如果我不能使用这种模式,那么其他方面是否可以在课堂上私有?
答案 0 :(得分:3)
您至少有四个选择:
解决方案grape_mao outlined,即Crockford's private pattern。它的问题是每个实例都获得了自己的 getMyVar
函数,它们无法共享它们。这是目前在JavaScript中获取真正私有属性的唯一方法。
解决方案Tibos outlined,其中myVar
不再是私有的,但所有原型函数都可以访问它,你没有为每个实例提供新的访问函数。 / p>
与#2相同的解决方案,在属性名称前面加上_
。纯粹作为惯例,名称以_
开头的属性应该禁止对象外部的代码。它不是远程私人的,但它很便宜。我曾经完全嘲笑这种方法,但是有人向我指出,现在大多数现代语言都有反射,私人成员即使在Java和C#等也不是私密的。 : - )
使用ES6 will use with private Name objects模式,用随机字符串替换私有Name对象(因为它们不存在!)。您的代码不担心属性的实际名称,其他代码无法合理地猜测它。仍然只是伪私人,但比#2或#3更私密;不如#1多。我概述了它的工作原理in this article。基本上它看起来像这样:
var MyObj = (function() {
var myVarName = new Name();
function MyObj(arg) {
this[myVarName] = arg;
}
MyObj.prototype.print = function() {
console.log(this[myVarName]);
};
return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2
...其中Name
看起来像这样:
var Name = function() {
var used = {};
function Name() {
var length, str;
do {
length = 5 + Math.floor(Math.random() * 10);
str = "_";
while (length--) {
str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
}
}
while (used[str]);
used[str] = true;
return new String(str); // Since this is called via `new`, we have to return an object to override the default
}
return Name;
}();
the article中的详细信息。
答案 1 :(得分:2)
您有MyObj
类的多个实例,但是您使用myVar
作为静态变量,因此它在实例之间共享。
此代码应该可以正常运行:
var MyObj = (function() {
function MyObj(arg) {
this.myVar = arg;
}
MyObj.prototype.print = function() {
console.log(this.myVar);
};
return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance1
instance2.print(); // instance2
演示:http://jsbin.com/EPirAki/1/edit
看一下这篇博文(简称T.J.Crowder - 见评论),它解释了如何使用随机来获得近乎私有的变量:http://blog.niftysnippets.org/2013/05/private-properties-in-es6-and-es3-and.html
答案 2 :(得分:1)
您需要一个可以访问该变量的权限函数。
var MyObj = (function() {
function MyObj(arg) {
this.getMyVar = function(){
return arg;
};
}
MyObj.prototype.print = function() {
console.log(this.getMyVar());
};
return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2
答案 3 :(得分:0)
原型函数不能直接访问私有变量。
var MyObj = (function() {
var abc = "shared by all MyObj"; // this variable is shared through all MyObj instances created and doesn't belong to MyObj
function MyObj(arg) {
var privateVar = arg;
this.getPrivateVar = function(){ return privateVar; }
this.myVar = arg;
}
MyObj.prototype.print = function() {
//console.log(privateVar); // cannot access variable
console.log(this.getPrivateVar()); // using a getter function you can access that private variable and limit its mutation
console.log(this.myVar);
};
return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2
答案 4 :(得分:0)
我对原型设计知之甚少,但我认为使用模块模式会产生更简单的东西,比如:
var MyObj = function(arg){
var myVar = arg;
var pub = {
print: function(){
console.log(myVar);
}
}
return pub;
};
var instance1 = MyObj('instance1');
var instance2 = MyObj('instance2');
instance1.print(); // instance1
instance2.print(); // instance2
同意,你没有这个'等级'。但对我来说,模块模式的重点是封装没有类似的麻烦。