{高级路径}详细解释了从原型链到组合继承的生成。
1。父类的实例对象被分配给子类的原型对象(原型),它可以继承。
功能人(){
this.username = 'ghostwu;
}
person.prototype.showusername =函数(){
返回this.username;
}
函数(教师){ }
teacher.prototype =新的人();
新教师();
console.log(OT。用户名); / / ghostwu
console.log(ot.showusername()); / / ghostwu
通过将父类(个人)的实例分配给子类教师的原型对象,它可以实现继承。子类的实例和实例可以访问父类的属性和方法。
如果你不画这幅画,你需要看我的文章:
{高级手工路}一步一步的原型(原型)对象javascript,原型链
第十一行执行ot.username。首先,它在OT上查找对象。显然,在OT对象没有属性,所以它会把teacher.prototype沿着OT的隐含的原型__proto__方向。
发现没有用户名的属性。Continue searching along Teacher.prototype.__proto__, and find new Person (). 这个例子有用户名的话,ghostwu价值。
所以停止查找,输出ghostwu。
第十二排在前面的ot.showusername执行相同的过程,但在新的人(),它没有找到showusername方法,并继续沿着新的人()。
隐含的原型__proto__定向(人。原型)的查找,和showusername发现person.prototype,停止查找,输出ghostwu。
二,将父类原型对象(原型)分配给子类的原型对象(原型),后者可以继承父类的方法,但继承父类的属性。
功能人(){
this.username = 'ghostwu;
}
person.prototype.showusername =函数(){
return'person::showusername法;
}
函数(教师){ }
teacher.prototype = person.prototype;
新教师();
console.log(ot.showusername()); / / ghostwu
console.log(OT。用户名); / /定义,用户名没有继承父类
因为老师。原型的隐式原型(__proto__)只分person.prototype,不去人实例的属性
三。继承关系之后,实例与构造函数(类)之间的关系。
或是和isprototypeof
功能人(){
this.username = 'ghostwu;
}
person.prototype.showusername =函数(){
返回this.username;
}
函数(教师){ }
teacher.prototype =新的人();
新教师();
console.log(或是老师); / /真的
console.log(或是人); / /真的
console.log(OT实例对象); / /真的
console.log(teacher.prototype.isprototypeof(OT) / /真实);
console.log(person.prototype.isprototypeof(OT) / /真实);
console.log(Object.prototype.isPrototypeOf(OT) / /真实);
四,父类的方法和属性,子类可以重写(重写),子类没有的方法和属性,并且可以扩展。
函数(人){ }
(person.prototype.showusername =功能){
console.log('person::showusername);
}
函数教师(){ }
teacher.prototype =新的人();
teacher.prototype.showusername =函数(){
console.log(::showusername);
}
teacher.prototype.showage =函数(){
(22)console.log;
}
新教师();
OT.showUserName(); / /老师::showusername
OT.showAge(); / / 22
五。改写后的原型对象,它实际上改变原型对象的__proto__方向。
对原型对象的原型__proto__方向改变了,和原来的继承关系上(切断)。
函数(人){ }
(person.prototype.showusername =功能){
console.log('person::showusername);
}
函数(教师){ }
teacher.prototype =新的人();
teacher.prototype = { {
showage:函数(){
(22)console.log;
}
}
新教师();
OT.showAge(); / / 22
OT.showUserName();
上面的例子中,第七行,重写teacher.prototype原型对象的老师(原型),隐含的原型第六行的原始对象(__proto__)点没有影响
所以在第十四排,ot.showusername()将导致调用错误,因为隐藏的原型(__proto__)教师的原型对象(原型)不再指向父类的实例(人),和继承关系被打破。
六。在继承过程中,仔细处理实例属性上引用类型的数据。
功能人(){
this.skills = { 'php ','javascript};
}
函数(教师){ }
teacher.prototype =新的人();
VaR OT1 =新教师();
VaR OT2 =新教师();
ot1.skills.push('linux);
console.log(OT2。技能); / / PHP,java,Linux
OT1的技能增加了一个Linux的数据,和其他实例可以因为技能数据共享在其他情况下,访问,和技能是一个引用类型
七。借用构造函数
为了消除引用类型对不同实例的影响,我们可以使用构造函数将引用类型的数据复制到每个对象,这样就不会相互影响。
功能人(uname){
this.skills = { 'php ','javascript};
this.username = uname;
}
person.prototype.showusername =函数(){
返回this.username;
}
老师的作用(uname){
(这person.call,uname);
}
VaR OT1 =新教师();
ot1.skills.push('linux);
VaR OT2 =新教师();
console.log(OT2。技能); / / PHP,Javascript
console.log(ot2.showusername());
虽然ot1.skills增添了Linux,不影响ot2.skills数据。它使用子类构造函数调用父类的构造函数,并复制父类的属性。
传递参数,例如第八行,但第十五行,方法调用错误,因为在构造中,只有复制属性不会复制到父类原型对象中。
八。组合继承(原型对象+借用构造函数)
通过以上分析,一个原型继承的缺点是:
1。参数不能转移,例如,
teacher.prototype =新的人();
有些人说括号后面可以跟着参数。是的,但是在所有参数中,子类的所有实例都是这样的。
2。在原型对象上放置引用类型会对不同实例产生相互影响。
单个借用人的缺点:
1。不能复制到父类的方法
正如原型对象方法的缺点一样,构造函数可以弥补它,借用构造函数的缺点,原型对象方法可以弥补它的不足。
功能人(uname){
this.skills = { 'php ','javascript};
this.username = uname;
}
person.prototype.showusername =函数(){
返回this.username;
}
老师的作用(uname){
(这person.call,uname);
}
teacher.prototype =新的人();
VaR OT1 =新老师('ghostwu);
ot1.skills.push('linux);
VaR OT2 =新老师('ghostwu);
console.log(OT2。技能); / / PHP,Javascript
console.log(ot2.showusername()); / / ghostwu
子类的实例OT2的技能不是由OT1的影响,和子类的实例,也可以调用父类的方法。
上面的js方法是从原型链继承的,它继承到了整个世代。详细的解释是,萧边分享了你的全部内容。我希望能给你一个参考,希望你能支持它。