js原型继承的几种方法

版权声明:本博文,由(曾梦想仗剑走天涯,现如今脱发眼已瞎)的Anles编写,可随意转载,你喜欢就好。 https://blog.csdn.net/qq_42926373/article/details/83149347

原型继承

首先创建一个构造函数,并为其设置私有属性和公有属性。

// 定义一个人类
    function Person (name) {
      // 属性
      this.name = name;
      // 实例方法
      this.sleep = function(){
        console.log(this.name + '正在睡觉!');
      }
    }
    // 原型方法
    Person.prototype.eat = function(food) {
      console.log(this.name + '正在吃:' + food);
    };

开始继承

原型继承有很多种方法,接下来就记录下我已知的几种方法。

第一种 原型链继承

重点圈起来:将父类实例赋值给子类原型对象

	// 创建子类、添加子类属性。
   function arrange(name){
     this.name = name;
     this.goShop = function(food){
       console.log(name + '叫你去买'+ food)
     }
   }
   // 将父类实例赋值给子类原型对象
   arrange.prototype = new Person();
   // 将constructor指向本身,保证原型链不断。
   arrange.prototype.constructor = arrange; 

   //创建arrange新实例,也是Person实例;
   var newObj = new arrange('李四'); 
   console.log(newObj instanceof Person)  //true
   console.log(newObj instanceof arrange) //true
   // 原型链继承成功,可以访问父类所有属性;
   console.log(newObj)
   console.log(newObj.name) // 李四
   newObj.sleep(); // 李四正在睡觉!
   newObj.eat('苹果'); // 李四正在吃:苹果
   newObj.goShop('香蕉'); // 李四叫你去买香蕉

第二种 构造继承

重点圈起来:执行父构造,将This指向本身,拉取父私有属性

	// 创建子类、添加子类属性。
	function arrange(name){
      Person.call(this,name) // 执行父构造,将This指向本身,拉取父私有属性;
    }
    arrange.prototype.getName = function(){
      console.log('我叫' + this.name)
    }
    var newObj = new arrange('李四');
    console.log(newObj)
    console.log(newObj.name) //李四
    newObj.sleep() // 李四正在睡觉!
    newObj.getName() //我叫李四

第三种 组合继承

重点圈起来:构造继承与原型继承组合。注意注释区域,切勿在继承时使用此方法重写或添加方法,否则将会修改整个原型,导致崩塌。

	// 创建子类、添加子类属性。
	function arrange(name){
      Person.call(this,name) // 执行父构造,将This指向本身,拉取父私有属性;
    }
    // 将父类实例赋值给子类原型对象
    arrange.prototype = new Person(); // 直接拉取父类实例继承原型
    // 将constructor指向本身,保证原型链不断。
    arrange.prototype.constructor = arrange;
    
    // 下面这个方法会替换整个原型对象
    // arrange.prototype = {
    //   init:function(){
    //     console.log('我会替换整个原型')
    //   }
    // }
    // 必须在原型实例继承之后,在给子类原型添加方法,或重写方法,请使用以下方法
    arrange.prototype.eat = function() {
      console.log(this.name + '重写了此方法');
    };
    arrange.prototype.addFn = function(){
      console.log(this.name + '添加了新方法' );
    }
    
    var newObj = new arrange('王五');
    console.log(newObj)
    newObj.eat(); // 王五重写了此方法
    newObj.addFn(); // 王五添加了新方法

第四种 克隆原型链继承

重点圈起来: 将等待继承的原型对象克隆,再赋值给继承的原型对象。此种方法会脱轨,不在同一原型链上

	// 创建子类、添加子类属性。
	function arrange(name){
      this.name = name;
      this.goShop = function(food){
        console.log(name + '叫你去买'+ food)
      }
    }
    // 创建克隆类型
    function Clone(obj){
      for(var key in obj){
        this[key] = typeof obj[key] == 'object' ? new Clone(obj[key]) : obj[key];
      }
    }
    // 使用Clone构造函数继承原型
    arrange.prototype = new Clone(Person.prototype); 
    // 将constructor指向本身,保证原型链不断。
    arrange.prototype.constructor = arrange; 

    //创建arrange新实例,也是Clone实例,却不在是Person实例;
    var newObj = new arrange('李四'); 
    console.log(newObj instanceof Person)  //false
    console.log(newObj instanceof arrange) //true
    console.log(newObj instanceof Clone) //true
    // 克隆成功,可以访问克隆对象的原型对象;
    console.log(newObj)
    console.log(newObj.name) // 李四
    newObj.eat('苹果'); // 李四正在吃:苹果
    newObj.goShop('香蕉'); // 李四叫你去买香蕉

第五种 寄生组合继承

重点圈起来: 将父类原型对象直接赋值给一个空属性的构造函数,再将空属性的构造函数实例赋值给子类原型对象,其根本是为了解决父实例继承的出现的两次构造。

	// 创建子类、添加子类属性。
	function arrange(name){
      Person.call(this,name)
      this.shop = function(){
        console.log(this.name + '去买好吃的,好吃就多吃点')
      }
    }

    (function(){
      // 创建一个没有实例方法的类
      var nullFn = function(){};
      nullFn.prototype = Person.prototype;
      //将实例作为子类的原型
      arrange.prototype = new nullFn();
       // 将constructor指向本身,保证原型链不断。
      arrange.prototype.constructor = arrange;
    })();
    
    var newObj = new arrange('老王');
    console.log(newObj)
    newObj.shop(); // 老王去买好吃的,好吃就多吃点
    newObj.sleep(); // 老王正在睡觉!
    newObj.eat('芭蕉'); // 老王正在吃:芭蕉

学习犹如逆水行舟,有舟就上。别问为什么,吾乃不踩坑学不会系列。

猜你喜欢

转载自blog.csdn.net/qq_42926373/article/details/83149347
今日推荐