Javascript 构造函数原型-继承混淆

Javascript 构造函数原型-继承混淆,javascript,constructor,prototype,Javascript,Constructor,Prototype,我首先定义两个独立的构造函数 var Sword = function (attack,price){ this.attack = attack; this.price = price; }; var LegendarySword = function (){ this.instantKill = true; }; 这些构造函数创建的对象显然彼此不相关 var sword = new Sword(1, 100); console.log(sword); //Object at

我首先定义两个独立的构造函数

var Sword = function (attack,price){
 this.attack = attack;
 this.price = price;
};

var LegendarySword = function (){
 this.instantKill = true;
};
这些构造函数创建的对象显然彼此不相关

var sword = new Sword(1, 100);
console.log(sword);

//Object
    attack: 1
    price: 100
    __proto__: Object


var superSword = new LegendarySword();
console.log(superSword);

//Object
    instantKill: true
    __proto__: Object
我现在希望所有的“类”传奇宝剑实例都具有剑“类”的特性,即攻击值和价格值。这是因为所有传说中的剑最终都是剑,但有一些独特的属性(比如“瞬间杀死”)

因此,在阅读了关于原型和继承的内容后,我发现我可以微笑着这样做:

LegendarySword.prototype = new Sword();
我理解这一行的方式是,在我构建LegendarySwarm类的新对象时,除了LegendarySwarm已有的构造函数之外,我还使用了Swarm的构造函数。我希望传说中的剑类物品获得攻击和价格属性,但同时我不希望剑类物品获得瞬杀属性

我还希望我现在能够在LegendarySwarm构造函数中提供参数:

var superSword2 = new LegendarySword (5, 1000);
我希望这会像剑构造器一样接受参数,但显然不是:

console.log(superSword2.attack); // results to undefined (which proves that it has them dug in somewhere in the __proto__,  which is so indeed)
看起来我仍然可以从另一个角度解决问题。如果我在创建一个新的传奇宝剑对象时,不必要地使构造函数复杂化,向宝剑添加新方法,调用这些方法并传递参数:

var Sword = function (attack,price){
 this.attack = attack;
 this.price = price;
    this.setAttack = function(attack){
    this.attack = attack;
};
this.setPrice = function(price){
    this.price = price;
};
};

var LegendarySword = function (attack, price){
 this.instantKill = true;
 this.setAttack(attack);
 this.setPrice(price);

};

LegendarySword.prototype = new Sword();

var sword = new Sword(1, 100);
console.log(sword);// gives correct object attributes

var superSword = new LegendarySword(10,5000);
console.log(superSword); // gives correct object attributes
但这真的很难看,我的问题是为什么Javascript不能在我调整构造函数原型时发现需要添加新属性?这对我来说太直观了

是否有其他方法可以解决此问题?

仅此而已 要解决您的问题,您只需执行以下操作:

var剑=功能(攻击、价格){
这个攻击=攻击;
这个价格=价格;
};
var legendarybrow=功能(攻击、价格){
this.instantKill=true;
剑。召唤(这个,攻击,价格)
};
var剑=新剑(1100);
控制台。日志(剑);//提供正确的对象属性
var superSword=新传奇宝剑(105000);
console.log(超级单词);//提供正确的对象属性
我希望这会像剑构造器一样接受参数,但显然不是:

console.log(superSword2.attack); // results to undefined (which proves that it has them dug in somewhere in the __proto__,  which is so indeed)
您不应该期望,修改构造函数的原型不会修改构造函数本身

> console.log(superSword2.attack);
> // results to undefined
> // (which proves that it has them dug in somewhere in
> //  the __proto__,  which is so indeed)
这并不能证明这一点。您不知道该属性是否存在,因为访问不存在的属性也会返回undefined(这就是本例中实际发生的情况)

当您这样做时:

LegendarySword.prototype = new Sword();
您只需将Legendary剑的默认原型替换为剑的实例,它不会修改Legendary剑本身,因此构造函数不会添加攻击和价格属性

如果您希望Legendary剑的实例具有与剑相同的属性,可以执行以下操作:

var LegendarySword = function (attack, price){

  // Add Sword properties
  Sword.call(this, attack, price);

  // Add LegendarySword properties
  this.instantKill = true;
};

这将设置所需的原型链,并使用剑属性初始化Legendary剑。

实际上可能有一种方法可以实现Child.prototype=Parent.prototype范式。关于这些方面,您怎么看:arguments.callee.prototype.constructor.apply(这是arguments);使用fiddle示例可能以下答案会有所帮助:它涵盖了构造函数和原型所扮演的角色,以及为什么创建父实例用作子实例是错误的。