Javascript原型继承私有方法

Javascript prototype inheritance private method

本文关键字:有方法 继承 原型 Javascript      更新时间:2023-09-26

我一直在研究JavaScript中每个"类"中"private"变量的多个继承级别,但遇到了这个奇点:

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;

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

>var a是在Ammo中定义的,但其他构造函数中的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);

在构造函数"调用超级"中:

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

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

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

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

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

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

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

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

除此之外,你的代码本身没有什么问题,只是不是人们通常编写"类"的方式,我不会在这个问题的上下文中解释为什么。