js中的继承

184 阅读1分钟

原型链继承

下面的例子中想解决的问题是,下面的函数也想拥有上面函数中的属性

function Father() {    
  this.name = 'father'
}
Father.prototype.getFatherName = function() {    
  return this.name
}
function Son() {   
  this.age = 12
}
Son.prototype.getSonName = function() {    
  return this.name
}
var son = new Son();
console.log(son.getFatherName())  //  son.getFatherName is not a function 

原型链继承之后,看下面

Son.prototype = new Father() 
// 这里相当于它重写了这个类的原型对象,他的原型对象本来拥有指向他的构造函数的指针,现在却指向了
另一个类的的实例,而实例对象又有指向原型对象的指针,说明它拥有了另一个类的原型链上的属性和方法。
Son.prototype.getSonName = function() {   
  return this.name
}
var son = new Son();
console.log(son.getFatherName()) // father

注意⚠️

上面的例子中,重写原型对象只能用那种方式,如果用对象字面量的话,就会有问题,具体看下面

function Father() {        
  this.name = 'father'  
}  
Father.prototype.getFatherName = function() {        
  return this.name
} 
function Son() {
 this.age = 12
} 
Son.prototype = {    
  name: 'father',
  getSonName: function() { 
     return this.name
  }
}
var son = new Son();
console.log(son.getFatherName()) // son.getFatherName is not a function 

这里son的实例对象已经指向了Object对象,他已经切断了Son和Father的联系

原型链继承的弊端, 属性会共享,相互影响

a从b继承来的属性c,a要是改了c,实例出来的d的属性c也变成了改变后的值

eg

function Father() {      
  this.arrs = [1,2,3]
}
function Son() {     
  this.age = 12
}
Son.prototype = new Father() 
var son1 = new Son();
son1.arrs.push(4)
console.log(son1.arrs) // [ 1, 2, 3, 4 ]
var son2 = new Son();
console.log(son2.arrs) // [ 1, 2, 3, 4 ]

借用构造函数继承(call,apply)

function Father() {      
  this.arrs = [1,2,3]
}
function Son() {     
  Father.apply(this)
}
var son1 = new Son();
son1.arrs.push(4)
console.log(son1.arrs) // [ 1, 2, 3, 4 ]
var son2 = new Son();
console.log(son2.arrs) // [ 1, 2, 3 ]

这个就会解决上面的问题

组合继承

借用构造函数实现实例属性的继承,使用原型链条实现原型属性和方法的继承