欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js原型继承的几种方法

程序员文章站 2022-06-15 16:02:20
...

原型继承

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

// 定义一个人类
    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('芭蕉'); // 老王正在吃:芭蕉

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

相关标签: 原型继承