Javascript 为什么在使用new关键字创建对象时,即使手动将对象的构造函数更改为另一个构造函数,也会执行该对象的构造函数?

Javascript 为什么在使用new关键字创建对象时,即使手动将对象的构造函数更改为另一个构造函数,也会执行该对象的构造函数?,javascript,object,Javascript,Object,在上面的代码中,我们从动物身上继承了鸟和狗。 他们的原型将是动物。所以默认情况下,Bird.constructor将指向动物构造函数 执行new Bird()时。我希望“动物登录控制台”,但鸟是登录的。因为构造器是动物。动物构造师应该被执行对吗?纠正我的理解您将继承与构造函数调用混淆了。当你说: function Animal() { console.log("Animal")} function Bird() { console.log("Bird")} function Dog() { co

在上面的代码中,我们从动物身上继承了鸟和狗。 他们的原型将是动物。所以默认情况下,Bird.constructor将指向动物构造函数


执行new Bird()时。我希望“动物登录控制台”,但鸟是登录的。因为构造器是动物。动物构造师应该被执行对吗?纠正我的理解

您将继承与构造函数调用混淆了。当你说:

function Animal() { console.log("Animal")}
function Bird() { console.log("Bird")}
function Dog() { console.log("Dog")}

Bird.prototype = Object.create(Animal.prototype);
Dog.prototype = Object.create(Animal.prototype);


 duck = new Bird();
 beagle = new Dog();
您正在对
Bird
构造函数进行显式调用,因此,
Bird
当然会触发


虽然
Object.create()
是一种使一个对象从另一个对象继承的简便方法,但仍然需要手动设置构造函数链。理解这一点的一个好方法是两个构造函数都接受参数(如下所示)

见内联评论:

功能动物(性别){
//参数允许初始化实例属性。
//性别将是动物的财产,并将被继承
//从动物身上继承下来的任何东西。但是
//不会改变动物构造师
//必须调用并传递动物的性别
//要正确初始化。
这个。性别=性别;
//获取此函数的调用方(非标准技术-仅用于演示)。
//如果调用方为空,则表示该动物被直接调用。如果不是,
//我们可以得到调用函数的名称:
var caller=Animal.caller?Animal.caller.name:“动物”;
//新建动物实验报告
log(“动物是一个”+this.gender+”(被称为“+caller+”));
}
功能鸟(性别,苍蝇){
//因为鸟是动物遗传的,所以你有
//手动确保在创建新鸟时
//将调用动物构造函数。您可以看到
//为什么这是必要的,因为我们的情况是
//原型的构造函数需要一个参数
//当
//已调用派生对象。我们当然不希望
//必须重写设定性别的代码,所以
//我们调用原型的构造函数并传递什么
//它期望并允许它执行某些对象
//为我们初始化:
Animal.prototype.constructor.call(这个,性别);
//将处理用于当前构造函数的参数
//在当前构造函数中
this.canFly=canFly
//继承的属性可用:
log(“鸟是一个“+this.gender+”,它会飞:“+this.canFly”);
}
//这只会使鸟从动物身上遗传下来。仅此一项
//新鸟()时不会导致动物构装师开火
//被执行。
Bird.prototype=Object.create(Animal.prototype);
//通过使用不同的原型,我们消灭了本地人
//构造函数,我们将只重置contstructor,以便
//鸟巢结构正常工作
Bird.prototype.constructor=Bird;
//只是一个测试来证明正确地制造动物
//要求调用Animal构造函数并
//通过性别鉴定。
console.log(“---创建新动物---”;
var generic=新动物(“雄性”);
//您在这里显式调用Bird构造函数。
//它将启动该功能。这一功能反过来,
//配置为调用原型对象的构造函数。
//性别属性将由动物构造师处理
//苍蝇将由鸟类建造师来处理。
console.log(“--creatingnewbird--”;
鸭子=新鸟(“雌性”,假);
// ************************************************
功能猎鹰(性别、苍蝇、训练){
//我们将把父对象所需的参数传递给它
Bird.prototype.constructor.call(this,gender,canFly);
//并在此处设置当前实例属性
这是经过训练的;
console.log(“鸟是一只“+this.gender+”,会飞:+this.canFly+”,被训练:+this.trained);
}
Falcon.prototype=Object.create(Bird.prototype);
//通过使用不同的原型,我们消灭了本地人
//构造函数,我们将只重置contstructor,以便
//Falcon的结构正常工作
Falcon.prototype.constructor=Falcon;
log(“---创建新的Falcon---”;

设f=新猎鹰(“雌性”,对,错)您将继承与构造函数调用混淆了。当你说:

function Animal() { console.log("Animal")}
function Bird() { console.log("Bird")}
function Dog() { console.log("Dog")}

Bird.prototype = Object.create(Animal.prototype);
Dog.prototype = Object.create(Animal.prototype);


 duck = new Bird();
 beagle = new Dog();
您正在对
Bird
构造函数进行显式调用,因此,
Bird
当然会触发


虽然
Object.create()
是一种使一个对象从另一个对象继承的简便方法,但仍然需要手动设置构造函数链。理解这一点的一个好方法是两个构造函数都接受参数(如下所示)

见内联评论:

功能动物(性别){
//参数允许初始化实例属性。
//性别将是动物的财产,并将被继承
//从动物身上继承下来的任何东西。但是
//不会改变动物构造师
//必须调用并传递动物的性别
//要正确初始化。
这个。性别=性别;
//获取此函数的调用方(非标准技术-仅用于演示)。
//如果调用方为空,则表示该动物被直接调用。如果不是,
//我们可以得到调用函数的名称:
var caller=Animal.caller?Animal.caller.name:“动物”;
//新建动物实验报告
log(“动物是一个”+this.gender+”(被称为“+caller+”));
}
功能鸟(性别,苍蝇){
//因为鸟是动物遗传的,所以你有
//手动确保在创建新鸟时
//将调用动物构造函数。您可以看到
//为什么这是必要的
Bird.prototype = Object.create(Animal.prototype);
duck = new Bird()
duck.eat("fish")