使用 IIFE 创建一个不是引用的类
Create a class with IIFE that isn't a reference?
我是JavaScript的新手,我正在尝试使用私有数据和公共函数创建"类"。我被告知立即调用的函数表达式 (IIFE) 可以完成此操作,但是当我从类中"实例化"新对象时,它们引用私有数据而不是保存自己的数据。
其中一些是从创建JS类中借用的:IIFE与返回原型
例如,一个简单的汽车"类":
var Car = (function() {
var body = { color: 'red' };
Car.prototype.newColor = function(color) {
body.color = color;
};
Car.prototype.getColor = function() {
return body.color;
};
return Car;
})();
var car1 = new Car();
var car2 = new Car();
Car2的颜色也变为紫色。
car1.newColor('purple');
car2.getColor(); // 'purple'
我希望 Car 类的每个对象都保存自己的私有数据。如何使用IFFE实现这一点,或者有其他方法?
模拟私有实例变量的唯一方法,它将它们声明为构造函数中的var myprivate
。
任何特权方法(=可以访问私有成员的方法)也必须在构造函数的主体中声明,因此不能在原型上(会花费额外的CPU和内存,并且在某些JS引擎中可能无法优化)。
我从来没有遇到过需要这样做的情况,因为在我看来,成本不值得。通常向我未来的自己和其他程序员表明,成员通过广泛使用的命名约定(名称以下划线开头)是私有的_myPrivate
"公共覆盖"的答案激发了我创建以下代码的灵感。私有实例成员可以由ben._data.set
公开访问,或者您可以重新实施规则和/或获取者/设置者,以便有人仍然可以滥用它。它仍然可以清理对象的可公开访问的成员,并使其更容易使用 getter 和 setter。
//Namespacing DataStore to limit scope of the closures
var tools = {
DataStore : function(){
var store = [];
this.get = function(key){
return store[key];
};
this.set = function(key,value){
store[key] = value;
return value;
};
}
};
//Person constructor
var Person = function(name){
//you can access this member directly
// bob.name = "Lucy";
this.name=name;
//if having _data as not accesable by defining
// with var _data we whould have to define
// get and set here as this.get and this.set
this._data=new tools.DataStore();
};
//constant value used to get or set, for example:
//ben.get(ben.AGE);
//Could add this and rules to Person instead of Person.prototype
//then you'll need a helper function to set up inheritance
//to make sure the static's on Person are copied to it's children
Person.prototype.AGE=0;
//rules for getters and setters
//Will be a problem with inheritance if on prototype
//function Employee(name){Person.call(this,name);};
//Employee.prototype=Object.create(Person.prototype);
//Employee.prototype.rules["0set"]=..overwrites Person.prototype.rules["0set"]
//When inheriting you need to have a helper function set the rules for a child
//object
Person.rules = {}
//rule for AGE set
Person.rules[Person.prototype.AGE+"set"] = function(val){
var tmp;
tmp = parseInt(val);
if(isNaN(tmp)){
throw new Error("Cannot set the age of the person "+
"to non number value, value of age:"+val);
}
if(tmp>150){
throw new Error("Are you sure this is a person and "+
"not a turtule? Trying to set age to:"+val);
}
return this._data.set(this.AGE,tmp);
};
//rule for age get
Person.rules[Person.prototype.AGE+"get"] = function(){
return this._data.get(this.AGE);
};
Person.prototype.get = function(key){
return Person.rules[key+"get"].call(this);
};
Person.prototype.set = function(key,value){
return Person.rules[key+"set"].call(this,value);
};
var ben = new Person("Ben");
ben.set(ben.AGE,22);
console.log(ben.get(ben.AGE));
try{
ben.set(ben.AGE,151);
}catch(e){
console.log("error",e);
}
try{
ben.set(ben.AGE,"HELLO WORLD!");
}catch(e){
console.log("error",e);
}
注意:如果要从 Person 继承,则需要将Person.rules
复制到子实例。
更多关于原型、继承、覆盖、调用超级、多重继承(混入)和this
值的信息:https://stackoverflow.com/a/16063711/1641941
但是这样你就定义了.privilegedMethod()
每次创建对象时,每个对象都将持有(相同目的)方法的不同版本......
我想出的解决方案是使用对象到对象(私有)哈希图,并将新创建的对象映射到 ctor 函数中的相应数据,并使用 hasmap 作为"管理器"来确定哪些数据对应于哪个对象,在原型方法中,如下所示:
var Car =
( function ( hashmap ) {
function PrivateClassCarData ( c, t ) {
this.color = c;
this.type = t;
}
function Car ( color, type ) {
hashmap.place( this, new PrivateClassCarData( color, type ) );
}
// read
Car.prototype.getColor =
function () {
return hashmap.read( this ).color;
};
// write
Car.prototype.setColor =
function (c) {
hashmap.read( this ).color = c;
return this;
};
// weak point, memory leak source
// dereference object from hash-map before updating variable that points to it
// another reference is kept in hashmap
// @TODO, automatic dereferencing execution, anybody?
Car.prototype.mfree =
function () {
hashmap.drop( this );
return this;
};
return Car;
} )(
// basic hash-map implementation
// maps objects to objects
( function ( hk, hv ) {
return {
place : function ( objKey, objVal ) {
hk.push( objKey );
hv.push( objVal );
return this;
},
read : function ( objKey ) {
return hv[ hk.indexOf( objKey ) ];
},
drop : function ( objKey ) {
var pos;
( ( pos = hk.indexOf( objKey ) ) != -1 )
&& (
hk.splice( pos, 1 ),
hv.splice( pos, 1 )
);
return this;
}
};
} )( [], [] )
);
var c1 = new Car("red","ferrary");
var c2 = new Car("white","porche");
c1.getColor();
// red
c2.setColor("silver");
c1.getColor();
// red
c2.getColor();
// silver
//
var Car =
( function ( cardb ) {
function Car ( color ) {
// facing the same problem here
// reinstaling .data() method for each created object
// but this way each has its own data store object
// and inner 1 to 1 circular reference js is able to deal with
cardb( this );
// set provided color parameter
this.data("color", color);
}
return Car;
} )(
// function to install .data() method to given object
// it gets attached to object directly, instead of
// attaching it to .prototype, in which case all
// object will access same data store
function ( obj ) {
var _data = {};
obj.data =
function ( name, value ) {
return arguments.length
? (
( value == null )
? _data[name]
: (
_data[name] = value,
this
)
)
: _data;
};
return obj;
}
);
var c1 = new Car("red");
var c2 = new Car("blue");
c1.data("color");
// red
c2.data("color");
// blue
c1.data("color","white");
c2.data("color");
// blue
c1.data("color");
// white
//
- AngularJS-你能在一个javascript块中引用一个中继器变量吗
- 在Node.js中,从同一文件中的另一个函数引用一个函数会导致'ReferenceError:-函数-未定义
- 两个指令引用一个变量,但第二个指令不引用;不要急于改变
- 将引用一个对象存储到Mongoose和MeanJS中
- 如何使用 JavaScript 引用一个部分
- 如何在 JQuery 的同一
中从另一个 引用一个 - 与许多事件侦听器和函数引用一个对象相比,什么是更好的方法
- 从另一个java脚本库引用一个
- 如何使用jQuery中的另一个变量按名称引用一个变量
- 有可能引用一个变量吗
- 引用一个html文件,并在另一个html文件中使用它们的字段
- 如何在同一Javascript对象中的另一个属性的值中引用一个属性
- jQuery:.on()使用普通对象中的事件来引用一个函数
- 如何引用一个按钮's被点击了,而不是被它的id点击了
- 如何引用一个较低的包(font-awesome)
- 引用一个DOM元素作为窗口对象的属性
- 如何从另一个PHP文件中引用一个变量?
- 在JavaScript中引用一个带有数值的对象属性
- 在s:url action属性中引用一个变量
- 两个javascript文件,引用一个库