开发者

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

开发者 https://www.devze.com 2023-03-06 01:09 出处:网络
I have this piece of code: var Human=function(name){ this._name=name; }; Human.prototype.Shout=function(){

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 additi开发者_JAVA百科onal instance of Human.


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.


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.


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

精彩评论

暂无评论...
验证码 换一张
取 消