Is there anyway to have instances share the same function yet at the same time have private variables?

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

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);           }     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!