原型链继承
- 每个构造函数都有一个原型对象prototype ,每个实例对象包含一个指向原型对象的指针proto,当代码读取实例的某个属性时,会首先在实例上搜索这个属性,如果没找到,则会去搜索原型对象。
- 缺点:包含引用类型的值的原型属性会被所有实例共享,如果一个实例改变了这个属性,那么其他实例的该属性也会被改变
js
复制代码
//原型链继承
function Animal(){
this.arr=[1,2,3]
}
function Cat(){
}
Cat.prototype=new Animal()
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 4, 1, 2, 3 ]
js
复制代码
//原型链继承
----------------写法一
function Animal(name){
this.name=name
}
Animal.prototype.run=function(){
console.log(this.name+'跑得快')
}
function Cat(name){
this.name=name
}
Cat.prototype=new Animal()
var cat1=new Cat("小花")
cat1.run()//小花跑得快
js
复制代码
//原型链继承
----------------写法二
function Animal(){
this.name="11"
}
Animal.prototype.run=function(){
return this.name
}
function Cat(){
this.name="12"
}
Cat.prototype=new Animal()
var cat1=new Cat()
console.log(cat1.run())//12
构造函数继承
- 构造函数继承,通过使用call或者apply方法,可以在子类中执行父类的构造函数,实现继承
- 优点:原型属性不会被共享
- 缺点:不会继承父类prototype上的属性(注意父类的方法还是可以继承的)
js
复制代码
//构造函数继承
function Animal(){
this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
Animal.call(this)
}
var dog=new Animal()
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 1, 2, 3 ]
console.log(dog.aa);//我是父类prototype上的属性
console.log(cat1.aa);//undefined
组合式继承(为了解决构造函数继承无法继承父类prototype的问题)
- 优点:原型属性不会被共享
- 可以继承父类的原型链上的属性和方法
- 缺点:调用了两次父类
- 在子类的prototype上添加了父类的属性和方法
js
复制代码
//组合式继承
function Animal(){
this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
Animal.call(this)
}
var dog=new Animal()
Cat.prototype=new Animal()--------------在构造函数继承上加入这一行代码
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 1, 2, 3 ]
console.log(dog.aa);//我是父类prototype上的属性
console.log(cat1.aa);//我是父类prototype上的属性
寄生组合继承
- 优点:原型属性不会被共享
- 可以继承父类的原型链上的属性和方法
- 只调用了一次父类,不会在子类的prototype上添加父类的属性和方法
- 缺点:子类的prototype的原始属性和方法会丢失
- 解决:放到Object.create后面执行
js
复制代码
//寄生组合继承
function Animal(){
this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
Animal.call(this)
}
Cat.prototype.run=()=>{
console.log('跑');
}
//创建的是一个没有实例方法的父类实例作为子类的原型
//但是寻找的时候会去有实例方法的父类原型上找
Cat.prototype=Object.create(Animal.prototype)
//指定构造函数的指向
Cat.prototype.constructor=Cat
var cat1=new Cat()
cat1.run()//error
cat1.arr.unshift(4)
console.log(cat1.arr)