js继承

1、原型式继承:借助构造函数的原型对象实现继承,即 子构造函数.prototype = 父构造函数.prototype.

function SuperClass(){
  this.name = 'lyj'
  this.sayName = function () {
    console.log('name:'+this.name)
  }
}
//设置构造函数的原型
SuperClass.prototype.age = 22
SuperClass.prototype.fridends = ['lily','kangkang'];
SuperClass.prototype.showAge = function () {
  console.log('age:'+this.age)
}

function SubClass() {
  
}
//这句执行表示子构造函数的constructor指向了父构造函数的的constructor
SubClass.prototype = SuperClass.prototype
//所以子构造函数需要修正constructor
SubClass.prototype.constructor = SubClass

//以上实现了继承,实例调用,实例的是子造函数
var child = new SubClass();
// child.sayName(); //这句会报错,不能继承构造函数的实例对象的成员
child.showAge(); //22
console.log(child.fridends)

缺点:只能继承父构造函数原型对象上的成员,不能继承父构造函数的实例对象的成员,同事父的原型对象和子的原型对象上的成员有共享问题。

2、原型链继承:即 子构造.prototype = 父构造函数的实例

function SuperClass(){
  this.name = 'lyj'
  this.age = 22
  this.sayName = function () {
    console.log('name:'+this.name)
  }
}
//设置构造函数的原型
SuperClass.prototype.fridends = ['lily','kangkang'];
SuperClass.prototype.showAge = function () {
  console.log('age:'+this.age)
}
function SubClass() {

}
//实现继承
SubClass.prototype = new SuperClass();
//修改constructor
SubClass.prototype.constructor = SubClass
//实例
let child = new SubClass()
child.sayName();
child.showAge();
console.log(child.age)
//修改实例的属性时,父构造函数的原型对象也会变化
child.fridends.push('wy')
console.log(child.fridends)
//看父函数的实例
let father = new SuperClass()
console.log(father.fridends)

缺点:不能给父构造函数传递参数,父子构造函数之间的原型对象有共享问题。

3、借用构造函数:使用call或apply借用其他构造函数的成员。

function Person(name){
  this.name = name
  this.friends = ['lyj','tll','wy']
  this.sayName = function () {
    console.log(this.name)
  }
}
function Student(name) {
  //使用call借用Person构造函数
  Person.call(this,name)
}
//实例化测试
var stu = new Student('小王八');
stu.sayName();
console.log(stu.friends)

缺优点:可以解决给父构造函数传递参数的问题,但是获取不到父构造函数原型上的成员,也不存在共享问题。

4、组合继承:即 借用构造函数 + 原型链继承

function Person(name,age){
  this.name = name
  this.age = age
  this.friends = ['lyj','tll','wy']
  this.sayName = function () {
    console.log(this.name)
  }
}
//父构造函数的原型对象
Person.prototype.showAge = function () {
  console.log(this.age)
}
function Student(name) {
  //使用call借用Person构造函数
  Person.call(this,name)
}
//设置继承
Student.prototype = new Person()
//修改constructor
Student.prototype.constructor = Student

//实例调用
var stu = new Student('lyj')
stu.sayName();//lyj
console.log(stu.friends)
//如果要使用age,需要实例化父构造函数
var per = new Person('jyl',22)
per.sayName()//jyl
per.showAge() //22
//不会改变子函数的值
stu.sayName()  //lyj
stu.showAge()//undefined

5、借用构造函数 + 深拷贝

function Person(name,age){
  this.name = name
  this.age = age
  this.friends = ['lyj','tll','wy']
  this.sayName = function () {
    console.log(this.name)
  }
  this.showAge = function () {
    console.log(this.age)
  }
}
function Student(name,age) {
  //使用call借用Person构造函数
  Person.call(this,name,age)
}
//使用深拷贝实现继承
deepCopy(Student.prototype,Person.prototype);
//修改子构造的constructor
Student.prototype.constructor = Student

//深拷贝函数(递归实现)
//将obj2的成员拷贝到obj1中,只拷贝实例成员
function deepCopy(obj1,obj2) {
  for(var key in obj2){
    if(obj2.hasOwnProperty(key)){
      //判断是否是引用类型的成员变量
      if(typeof obj2[key] == 'object'){
        obj1[key] = Array.isArray(obj2[key])?[]:{}
        deepCopy(obj1[key],obj2[key])
      }else{
        obj1[key] = obj2[key]
      }
    }
  }
}
//实例化使用
var stu = new Student('llllyj',25)
stu.sayName()
stu.showAge()

你可能感兴趣的:(js继承)