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的继承有6种方式,大致总结一下它们各自的优缺点,以及它们之间的关系。 1.原型链 js的继承机制不同...
    空_城__阅读 802评论 0 11
  • 继承的概念:子类可以使用父类共享的属性和方法,避免重复代码提高代码复用性。 原型链:子类可以共享父类的实例对象和实...
    浅秋_6672阅读 420评论 0 0
  • 一、原型链 学过java的同学应该都知道,继承是java的重要特点之一,许多面向对象的语言都支持两种继承方式:接口...
    grain先森阅读 1,435评论 0 39
  • 作者:撒网要见鱼http://www.dailichun.com/2018/01/15/howtoextendda...
    grain先森阅读 710评论 0 3
  • 继承6种套餐 参照红皮书,JS继承一共6种 1.原型链继承 核心思想:子类的原型指向父类的一个实例 Son.pro...
    灯不梨喵阅读 3,193评论 1 2