【问题标题】:Javascript prototype inheritance private methodJavascript原型继承私有方法
【发布时间】:2015-03-19 16:29:01
【问题描述】:

我一直在研究 JavaScript 中每个“类”中的“私有”变量的多层次继承,但遇到了这个奇特的奇点:

function Ammo() {
    var a = 0;
    this.get_ammo = function() {
        return a;
    };

    this.add_to_ammo = function() {
        a = a+1
        return a;
    };

    this.clean_ammo = function() {
        return a=0;
    }
}

function Weapon() {
    var a =0;
}

function Gun() {
    var a = 0;
    this.fire = function(){
        console.log("Bang");
    }
}

Weapon.prototype = new Ammo();
Weapon.prototype.constructor  = Weapon();

Gun.prototype = new Weapon();
Gun.prototype.constructor = Gun();

var a = new Ammo();
var w = new Weapon();
var g = new Gun();

a.add_to_ammo()
a.add_to_ammo()
a.add_to_ammo()
console.log(w.get_ammo())
// At this point I get 0, as expected. But after
w.add_to_ammo()
w.add_to_ammo()
w.add_to_ammo()
console.log(g.get_ammo())
// But here I get 3!

谁能解释一下为什么我得到 3 之后

console.log(g.get_ammo())

我认为对象 a、w、g 是独立的,它们的域也是如此。

我还发现如果我改变了

var a = 0;

this.a = 0;

我得到了预期的结果。对象的字段未绑定到其父字段。

【问题讨论】:

    标签: javascript inheritance prototype


    【解决方案1】:

    var aAmmo 中定义,但在其他构造函数中的var a 绝对什么都不做。 a 在调用该方法时被修改,无论哪个实例始终与在 Ammo 的闭包中捕获的 a 相同。

    您不能像在 JavaScript 中那样拥有私有变量,这没关系。最常见的方法是将变量公开,并在其前面加上下划线,将其标记为“内部”:

    function Ammo() {
      this._ammo = 0;
    }
    

    然后将方法添加到prototype 并使用this._ammo 引用该变量:

    Ammo.prototype.getAmmo = function() {
      return this._ammo
    }
    

    那么你就可以用Object.create继承了:

    Weapon.prototype = Object.create(Ammo.prototype);
    

    并在构造函数中“调用super”:

    function Weapon() {
      Ammo.call(this) // gets own "_ammo"
    }
    

    另外,您没有正确设置构造函数。您应该分配一个函数,而不是调用它:

    Weapon.prototype.constructor = Weapon;
    Gun.prototype.constructor = Gun;
    

    【讨论】:

      【解决方案2】:

      我没有足够的代表点来评论@elclanrs 的答案,所以请原谅我。

      他的答案都是正确的,但最相关的信息是最后一条

      另外,您没有正确设置构造函数。您应该分配一个函数,而不是调用它:

      Weapon.prototype.constructor = Weapon;
      Gun.prototype.constructor = Gun;
      

      在函数闭包范围内声明的变量实际上是私有的!然而,你从来没有正确地实例化你的子类对象,所以你有一个弗兰肯斯坦的事情发生:一个对象,很多身体部位。

      除了您的代码本身没有任何问题外,这不是人们通常编写“类”的方式,我不会在这个问题的上下文中解释原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-09
        • 2010-09-28
        • 2018-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多