可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have this piece of code:
var Human=function(name){ this._name=name; }; Human.prototype.Shout=function(){ alert(this._name); }; var tom=new Human("tom"); var john=new Human("john"); alert(tom.Shout===john.Shout);
Right now ._name is not "private". I want to make ._name "private", but at the same time i do not wish to create additional functions for each instance of Human (in other words tom.Shout Must be === to john.Shout) because creating additional functions for each instance is just well.. unnecessary (ok offtopic - we can debate this on another thread)
My conclusion is that what I'm trying to achieve (having ._name be "private" and at the same time having tom.Shout===john.Shout
) is impossible.
But I just want to be 200% sure before jumping into any conclusions.
(I welcome any hacks as long as the requirements are met, i.e no creating of additional functions for each instance)
If we have to create additional functions to do scoping that's fine but that number should be a fixed number and that number should not increase with each additional instance of Human.
回答1:
Update
Your looking for @name
which is an instance variable. Pray it's in es.next, but we don't have it yet. Maybe in two years.
If you care about a clean API then here is your solution:
function Class(foo) { Class.priv(this).foo = foo; } Class.priv = (function() { var cache = [], uid = 1; return function(obj) { if (!this.__id) { this.__id = uid; cache[uid++] = {}; } return cache[this.__id]; }; }()); Class.prototype.bar = function() { console.log(Class.priv(this).foo); }
Store all the data in a cache as a function of the constructor. No data is cluttered on the object.
Original
However there is no such thing as "private".
All you can do is create a local variable inside a function.
The constructor function
var Human = function(name) { // local variable. var _name = name; }
Has a local variable that by very definition of being local is not usable outside of the constructor function.
This means that you cannot access it in external code like the prototype.
What you can do however is make it read only using ES5
var Human = function(name) { Object.defineProperty(this, "name", { value: name }); }
If you can truly achieve what your asking, you'd make a huge breakthrough in js. I've attempted to do just that for many hours.
A different pattern would be :
var Human = function(name) { this.name = name; return { Shout: this.Shout.bind(this) }; } Human.prototype.Shout = function() { console.log(this.name); }
This has the overhead of calling .bind
and creating a new object for every instance though.
回答2:
how about this ?
var Human = function (name) { var _name = name; this.getName = function () { return _name; } }; Human.prototype.Shout = function () { alert(this.getName()); }; var tom = new Human("tom"); var john = new Human("john"); tom.Shout(); // tom john.Shout(); // john alert(tom.Shout === john.Shout); // true
EDIT: the former creates another function for GET property, it is not possible without creating additional functions.
回答3:
Did read the question, didn't understand, because this._name
is just not private, so the question is a bit weird. This is how in my test the prototype methods are added once and available to all instances. I repeat: this._name
is not private here. If you add a local variable, and want to access it via a closure in a prototype method, calling the value of the local variable will result in the same value for all instances.
Anyway, with this constructor function the this._name getter and shout methods are added to the prototype chain once and thereby available for all instances of Human.
function Human(name) { if (!(this instanceof Human)){ return new Human(name); } this._name = name; if (!Human.prototype.Name){ Human.prototype.Name = function(val){ if (val){ this._name = val; return this; } return this._name; }; Human.prototype.shout = function(){ alert(this._name); } } }