我正在尝试使用Stefan Stoyanov的Javascript Patterns中描述的“揭示模块”模式(构造函数版本)。
我有一个简单的Point对象,它有两个私有变量_x和_y。当我尝试使用不同的_x和_y创建Point的多个实例时,所有实例看起来都指向同一个对象。它们具有相同的_x和_y变量值。
这是我工作的jsFiddle示例的链接,它演示了确切的问题。
那么我如何确保不共享私有变量,同时仍将它们保密(在构造函数中将它们设置为'this'使它们可以直接访问)?我相信我想做的事情是可能的,我是对的吗?
仅供参考我的代码:
var Point = (function() {
// Trying to use the revealing module pattern, as described in the book Javascript Patterns by Stoyan Stefanov'
// Private. Should only be accessible externally by public methods.
var _x, _y;
// Constructor
var Constr = function(x, y) {
_x = x;
_y = y;
}
var getX = function() {
return _x;
}
var getY = function() {
return _y;
}
var toString = function() {
return getX() + ", " + getY();
}
// Prototype. These are the public functions that are being "revealed"
Constr.prototype = {
constructor: Point,
getX: getX,
getY: getY,
toString: toString
}
return Constr;
})();
var pt1 = new Point(100, 100);
var pt2 = new Point(200, 200);
var pt3 = new Point(300, 300);
var pt4 = new Point(400, 400);
// Problem: Points all share the same private variables.
alert("pt1: " + pt1);
alert("pt4: " + pt4);
答案 0 :(得分:3)
您的私有变量是IIFE的一部分,因此它们将被创建一次,然后或多或少 static 到每个其他对象实例化。您需要在this
对象内部设置Constr
的属性。
或者,您可以在Constr()
构造函数内部分配函数并使用普通var
变量。这虽然有一些缺点......
revealing module pattern(免责声明:我自己的博客)旨在隐藏在外部世界中使用的某些方法和属性,但此模式不适用于对象实例这需要他们自己的实例数据。
答案 1 :(得分:2)
对于有类似问题的其他人;下面更新的代码现在符合我的私人变量外部无法访问的主要要求。
这是可能的,因为我将函数和变量定义为构造函数中的locals。但是,这也意味着每个实例都有自己的函数副本(内存使用效率低下)。
原型方法将确保实例之间只共享一个函数副本,但这使得无法访问不可访问的私有变量。如果有任何错误,请纠正我,我会更新,我很想知道这是否真的可行。
var Point=(function() {
// Constructor
var Constr = function(x, y) {
// Private
var _x = x;
var _y = y;
var privateFunc=function(str) {
alert('Private: ' + str + ' ' + _x);
}
// Public
this.getX = function() {
return _x;
};
this.getY = function() {
return _y;
};
this.toString = function() {
return this.getX() + ", " + this.getY();
};
}
// Prototype.
Constr.prototype = {
constructor: Point
}
return Constr;
})();
var pt1 = new Point(100, 100);
var pt2 = new Point(200, 200);
var pt3 = new Point(300, 300);
var pt4 = new Point(400, 400);
alert("pt1: " + pt1);
alert("pt2: " + pt2);
alert("pt3.getX(): " + pt3.getX());
alert("pt4._y: " + pt4._y);
//alert(pt4.privateFunc('123'));
答案 2 :(得分:1)
你可以用技巧做你想要的(用原型函数访问私有变量)。
var Point = (function() {
// Private storage. Not accessible directly outside the closure
var reg = [];
// Constructor
var Constr = function(x, y) {
var privates = {x:x, y:y};
reg.push(privates);
this._key = reg.length - 1;
}
var getX = function() {
return reg[this._key].x;
}
var getY = function() {
return reg[this._key].y;
}
var toString = function() {
return this.getX() + ", " + this.getY();
}
Constr.prototype = {
constructor: Point,
getX: getX,
getY: getY,
toString: toString
}
return Constr;
})();
var pt1 = new Point(100, 100);
var pt2 = new Point(200, 200);
var pt3 = new Point(300, 300);
var pt4 = new Point(400, 400);
// Points all share the same accessors which look up the private registry via this._key
alert("pt1: " + pt1);
alert("pt4: " + pt4);
但也有缺点: