JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦。而在js中每个函数都有个原型,我们可以通过找原型进行继承的方法,在不对B中的属性或方法重写的前提下实现对A函数的继承。
那么我们构造一个函数:属性写在函数内,方法写在原型(.prototype)中,这样我们可以通过一级一级的找原型来实现继承。
function Baby(name,isMale,birthdate){
this.name = name;
this.isMale = isMale;
this.birthdate = birthdate;
//年龄可以通过生日计算得出,所以可以通过get方法来定义
//这个属性
Object.defineProperty(this,"age",{
get:function(){
var age = new Date().getFullYear()-this.birthdate.getFullYear();
return age;
}
});
}
//这是函数的方法
Baby.prototype.eat = function(food){
console.log(this.name+"吃了"+food);
}
Baby.prototype.sleep = function(hours){
console.log(this.name+"睡了"+hours+"个小时");
}
如果我们再写一个构造函数,而这个新的构造函数中有A函数的属性和方法,很多时候我们会这样写:
function Child(name,isMale,birthdate){
this.name = name;
this.isMale = isMale;
this.birthdate = birthdate;
..........
//如果把所有的属性赋值都再写一次,逻辑上没有错误,
//但是代码上很浪费,因为Child构造函数中的代码和Baby函数
//中的代码一模一样,如果能够把Baby函数中的代码放在此处
//执行,效率会提高很多。
对于方法的继承我们可能会这样写:Baby(name,isMale,birthdate);那么这样就会导致这两个函数中的this所指定的内容不同
如果在此直接调用Baby函数,那么Baby函数中的this不是
本函数中的this,而是window,就会造成属性没有赋值给
我们正在创建的对象,而是赋值给了window。
当我们对一个函数的属性进行继承的时候我们可以通过call()进行调用:
Baby.call(this,name,isMale,birthdate);写在Child函数中,也就是调用了Baby的属性
方法的继承:
Child.prototype = Object.create(Baby.prototype);Object.create 创建一个对象并指定这个对象的原型
Child.prototype.constructor = Child;
//自己设置的原型需要手动设置 原型的构造函数。
//设置了原型的构造函数之后,通过查看对象的原型中的
//constructor,就可以知道这个对象是用哪个构造函数创建的
//,相当于知道这个对象是什么类型。
//JavaScript中没有类的概念,继承通过原型链实现,当一个
//构造函数B要继承构造函数A时,只要将B的原型的原型设置为A的
//原型即可。