反正有没有实例共享相同的功能但同时有私有变量?

时间:2011-05-13 22:41:22

标签: javascript function ecmascript-5

我有这段代码:

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

现在._name不是“私人”。我想使._name“私有”,但同时我不希望为每个人类实例创建额外的函数(换句话说,tom.Shout必须是===到john.Shout),因为创建了附加函数每个实例都很好..不必要(ok offtopic - 我们可以在另一个线程上讨论这个)

我的结论是,我想要实现的目标(将._name设为“私有”,同时拥有tom.Shout===john.Shout)是不可能的。

但我只想在得出任何结论之前保持200%的肯定。

(只要符合要求,我就欢迎任何黑客攻击,即不为每个实例创建额外的功能)

如果我们必须创建其他函数来进行范围确定,那么这个数字应该是一个固定的数字,并且该数字不应该随着每个额外的Human实例而增加。

3 个答案:

答案 0 :(得分:3)

<强>更新

您正在寻找@name这是一个实例变量。在es.next中祈祷它,但我们还没有。也许两年后。

如果您关心干净的API,那么这是您的解决方案:

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

将所有数据存储在缓存中,作为构造函数的函数。对象上没有数据混乱。

<强>原始

然而,没有“私人”这样的东西。

您所能做的就是在函数内创建一个局部变量。

构造函数

var Human = function(name) {
    // local variable.
    var _name = name;
}

有一个局部变量由于本地的定义,在构造函数之外是不可用的。

这意味着您无法在原型等外部代码中访问它。

但是,您可以使用ES5

进行只读
var Human = function(name) {
    Object.defineProperty(this, "name", { value: name });
}

如果你能真正实现你的要求,你就会在js上取得巨大的突破。我试图这么做几个小时。

不同的模式是:

var Human = function(name) {
   this.name = name;

   return {
       Shout: this.Shout.bind(this)
   };
}

Human.prototype.Shout = function() {
   console.log(this.name);
}

这会产生调用.bind并为每个实例创建新对象的开销。

答案 1 :(得分:1)

怎么样?

    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

编辑: 前者为GET属性创建了另一个函数, 没有创建额外的功能是不可能的。

答案 2 :(得分:1)

读过这个问题,不明白,因为this._name不是私密的,所以问题有点奇怪。这就是my test中原型方法添加一次并可用于所有实例的方式。我再说一遍:this._name在这里不是私密的。如果添加局部变量,并希望通过原型方法中的闭包访问它,则调用局部变量的值将为所有实例生成相同的值。

无论如何,使用这个构造函数,this._name getter和shout方法被添加到原型链中一次,从而可用于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);
          }
    }
}