js实现的几种继承方式

js实现的几种继承方式


1、借用构造函数继承

  • 优点:可以继承实例属性
  • 缺点:原型中的方法无法继承
  • 关键点:通过call的方式,修改this的指向
// 设置需要被继承的构造函数Animal
function Animal(name, age) {
  this.name = name;
  this.age = age;
}
// 原型方法
Animal.prototype.eat = function() {
  console.log('吃各种好吃的')
}

// 再设置一个猫咪构造函数
 function Cat(name, age) {
   Animal.call(this, name, age)
 }
 var cat = new Cat('jack', 18)
 console.log (cata);// 属性继承,但原型中的方法没有继承

2、原型继承

优点:

  • 可以继承原型中的方法。
    缺点:

  • 实例属性虽然有,但是无法传参(跟没有一样)

  • 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行 否则会被覆盖

  • 无法实现多继承

  • 需要重新设置被覆盖的constructor属性 让constructor重新指向Cat

关键点:

  • 原型链:查找规则,优先查找自身,如果没有则查找__proto__中是否存在; 原型链是用来描述实例对象与原型对象之间关系的一种方式。
  function Animal(name, age) {
    this.name = name;
    this.age = age;
  }
  Animal.prototype.eat = function() {
    console.log('吃各种好吃的')
  }

  function Cat(color) {
    this.color = color;
  }

  // 继承的核心代码 必须写在前面 ,否则会覆盖子类的方法
  Cat.prototype = new Animal('jack', 18); 
  设置被覆盖的constructor属性 让constructor重新指向Cat
  Cat.prototype.constructor = Cat;
  Cat.prototype.shangshu = function() {
    console.log('猫咪会爬树');
  }
  var cat = new Cat();
  console.log(cat);
  console.log(cat.name)//jack
  console.log(cat.age)//18

3、组合继承

  • 使用前面两种继承方式时发现各有优缺点,所以将两种方式结合即可。
  • 这种结合使用的方式称为组合继承,组合继承是最常用的一种继承方式。

总结一下原型链:

  • 原型链:查找规则,优先查找自身,如果没有则查找_ proto _中是否存在; 原型链是用来描述实例对象与原型对象之间关系的一种方式
  • Animal构造函数在设置时没用继承自其它的构造函数
  • Animal的原型对象也是一个对象
  • 对象都是通过Object这个构造函数创建的
  • Animal.prototype这个对象_ proto _就应该指向Object.prototype
  • 通过观察我们发现确实含有一个属性constructor,并且值为Object构造函数
  • Object.prototype中没有_ proto 属性了,说明这个对象是原型对象的终点。若果使用一个对象的属性时,在整个原型对象中均没找到,值即为undefined Object。prototype. proto _打印为null
  • 扩展:在作用域中,都没有找到会报错
  function Animal(name, age) {
    this.name = name;
    this.age = age;
  }
  Animal.prototype.eat = function(){
    console.log("吃各种吃的");
  };

  function Cat(name,age,color){
    //使用借用构造函数的方式继承:
    Animal.call(this,name,age);
    this.color = color;
  }

  //原型继承的核心代码:
  //使用组合继承方式后,在构造函数体中就设置了实例属性,此处不需要传参
  Cat.prototype = new Animal();
  //设置被覆盖的constructor属性
  Cat.prototype.constructor = Cat;
  Cat.prototype.shangShu = function(){
      console.log("猫咪可以爬树");
  };

  var Cat = new Cat("rose",20,"red");
  console.log(Cat);

4、对组合继承的优化方式

个人认为:

  • 虽然可以省去不需要继承的实例属性
  • 这种方式的确会比组合继承的方式性能更好,但是略麻烦(了解即可)
  function Animal(name,age){
    this.name = name;
    this.age = age;
  }
  Animal.prototype.eat = function(){
    console.log("吃各种吃的");
  };


  function Cat(name,age,color){
    //使用借用构造函数的方式继承:
    Animal.call(this,name,age);
    this.color = color;
  }

  //原型继承方式中希望获取到Animal的原型方法
  //Cat.prototype = new Animal();

  //可以省去不需要继承的实例属性
  //这种方式的确会比组合继承的方式性能更好,但是略麻烦(了解即可)
  function Fun (){}
  Fun.prototype = Animal.prototype;
  Cat.prototype = new Fun();

  Cat.prototype.constructor = Cat;
  Cat.prototype.shangShu = function(){
    console.log("猫咪可以爬树");
  };
  
  var cat = new Cat("rose",20,"red");
  console.log(cat);

5、拷贝继承

  • 优点:使用继承的原型中的方法时,查找的次数会降低
  • 缺点:效率较低,内存占用高(因为要拷贝父类的属性)
  function Animal(name,age){
    this.name = name;
    this.age = age;
  }
  Animal.prototype.eat = function(){
    console.log("吃各种吃的");
  };

  function Cat(name,age){
    Animal.call(this,name,age)
  }

  //核心代码
  for(var k in Animal.prototype){
    Cat.prototype[k] = Animal.prototype[k];//添加属性
  }
  Cat.prototype.constructor = Cat;
  Cat.prototype.shangShu = function(){
    console.log("猫咪可以爬树");
  };
  var cat = new Cat("rose",20,"red");
  console.log(cat);

6、补充一下:对象之间的继承

  var obj={
    name: 'jack',
    age: 12,
    gender: '男',
    sayHai: function() {
      console.log("我是人")
    }
   }
   // 问题:obj2想要继承obj的属性
   // (1)拷贝继承:
   var obj2 = {};
   for(var k in obj) {
     obj2[k] = obj[k];
   }
   //(2)原型继承:
   function Fun() {};
   Fun.prototype = obj;
   var obj2 = new Fun();
   console.log(obj2);

详情来源本人博客:https://shengchangwei.github.io/some-inheritance/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值