6

我有这段代码:

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 设为“私有”,但同时我不希望为 Human 的每个实例创建额外的函数(换句话说,tom.Shout 必须 === 到 john.Shout),因为为每个实例都很好..不必要(好的题外话 - 我们可以在另一个线程上讨论这个)

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

但我只想在得出任何结论之前有 200% 的把握。

(只要满足要求,我欢迎任何 hack,即不为每个实例创建附加功能)

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

4

3 回答 3

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但是,这具有为每个实例调用和创建新对象的开销。

于 2011-05-13T23:33:13.420 回答
1

看了题,没看懂,因为this._name不是私信,所以题有点奇怪。这就是在我的测试中,原型方法被添加一次并且可用于所有实例的方式。我再说一遍: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);
          }
    }
}
于 2011-05-13T23:50:37.360 回答
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 属性创建另一个函数,如果不创建附加函数是不可能的。

于 2011-05-13T22:46:30.940 回答