每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个原型对象的指针(constructor)并指向原想对象。
继承的本质就是复制,即重写原型对象,代之以一个新类型的实例
JS的继承给我独特的印象是,
在java中,继承是复制父类的一份给自己,即使自己把复制过来的东西弄坏了,也不会影响到父类那边的
而js中是通过原型继承,自己弄坏(修改)的,会直接影响到父类本身的东西
原型继承
原型链
访问一个对象的属性时,先在基本属性中查找,
如果没有,再沿着_proto_这条链向上找,这就是原型链。
举一个例子说明下吧:
在实际应用中如何区分一个属性到底是基本的还是从原型中找到的呢?
答案就是:hasOwnProperty这个函数,特别是在for…in…循环中,一定要注意。
但是!!
f1本身并没有hasOwnProperty这个方法,那是从哪里来的呢?
答案很简单,是从Object.prototype中来的。看下图:
对象的原型链是沿着__proto__这条线走的,
因此在查找f1.hasOwnProperty属性时,就会顺着原型链一直查找到Object.prototype。
继承
由于所有对象的原型链都会找到Object.prototype,
因此所有对象都会有Object.prototype的方法。这就是所谓的“继承”。
class继承
class也就是类
哺乳动物类
我们可以把哺乳动物类归为一个类,
他们有一些共同的特点,例如身体表面长毛,胎生、小时候吃奶。
猫科动物类
而猫科动物类继承自哺乳动物类,这些猫科动物不仅有自己的特征,
例如习惯于夜间活动、听觉灵敏等
而同时猫科动物也继承着哺乳动物胎生、吃奶这些特点
豹子类
豹子类继承着猫科动物类的特征,同时也有自己的特征,
例如有许多斑点和金黄色的毛皮、奔跑速度极快等
(图只是表示个意思,莫深究)
class mammals{
constructor(name) {
this.name=name
}
eat(){
console.log(`${this.name}`);
}
}
class Leopard extends mammals{
constructor(name,age){
super(name)
//但凡看到extends继承那这句就固定加上super
//相当于es5中Animal.call(this,name)
//super()负责初始化this.相当于ES5中的call和apply方法。
this.name=name
this.age=age
}
say(){
console.log(`${this.name}=>${this.age}`)
}
}
let leopard=new Leopard("baozi",2);
Leopard.say()
Leopard.eat()