The only way to simulate private instance variables it to declare them as var myprivate
in the constructor function.
Any privileged method (=method that can access the private member) has to be declared within the constructor function's body as well so can't be on the prototype (will cost you extra cpu and memory and maybe doesn't optimize as well in some JS engines).
I never had a situation where it was needed to do this since in my opinion the cost is not worth the gain. Usually indicate to my future self and other programmers that a member is private by a widely used naming convention (name starts with underscore) _myPrivate
"Public override"'s answer inspired me to create the following code. Private instance members can be accessed publicly by ben._data.set
or you could re implement rules and or getters/setters so someone could still abuse it. It can still clean up you're object's publicly accessible members and making it easier to use the getters and setters.
//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);
}
Note of caution: Person.rules
needs to be copied to Child instances when you want to inherit from Person.
More about prototype, inheritance, overriding, calling super, multiple inheritance(mix in) and the value of this
here: https://stackoverflow.com/a/16063711/1641941
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…