美文网首页
原型、原型链、继承(构造函数继承,非构造函数继承)

原型、原型链、继承(构造函数继承,非构造函数继承)

作者: silly鸿 | 来源:发表于2018-03-13 17:12 被阅读0次

    一、原型

    在JS设计出来的时候,只是为了实现一样网页的简单交互,并没有想过把JS设计成为一门面向对象的语言。后来的发展,JAVA和C++等语言都有了自己的Class用于继承,所以JS也想要实现继承,所以就出现了原型prototype

    二、原形链

    function Person(){
    }
     var p = new Person()
    

    对应的原型链结构为


    凡是构造函数都有一个原型属性prototype
    凡是对象都有一个原型,通过__proto__可以访问原形,访问到的原型又是对象,那么如此下去,就会构成一个对象的序列,该结构称为原型链

    默认的原型链就是:
    当前对象-->构造函数.prototype-->Object.prototype--null

    注意: 原型和实例上都有一个constructor构造器指向构造函数
    Function.prototype.constructor === new Function().constructor

    三.构造函数继承

    构造继承
    原型继承
    实例继承(闭包继承)
    拷贝继承
    组合继承
    寄生组合继承

    优缺点考虑方向: 实例化的次数,是否父类子类实例,是否可以复用

    1.构造继承

    使用父类的构造函数来增强子类实例,等于赋值父类的实例属性给子类

        function Animal(){
            this.species  = "动物";
        }
        function Cat(name){
            Animal.call(this)
            Animal.apply(this)
            //相当于 Animal()
            //this.species = '动物' this指向Cat内部
            console.log(this)//Cat
            this.name = name;
        }
    
        var cat = new Cat("大毛")
    

    缺点:
    1.实例并不是父类的实例,只是子类的实例
    2.只能继承父类的实例属性和方法,不能继承原型属性和方法

    2.原型继承

    使用构造函数的prototype指向父对象的一个实例,需要注意把子构造函数的constructor构造器重新指向自己,因为使用prototype指向了父构造函数的prototype,会出现原型链紊乱

        Cat.prototype = new Animal();
        Cat.prototype.constructor = Cat;
       var cat1 = new Cat("大毛","黄色");
       alert(cat1.species); // 动物
    

    原型继承升级版

     function Animal(){ }
     Animal.prototype.species = "动物";
    
       Cat.prototype = Animal.prototype;
       Cat.prototype.constructor = Cat;
       var cat1 = new Cat("大毛");
       alert(cat1.species); // 动物
    

    缺点:
    1.无法实现多继承
    2.创建子类实例时,无法想父类构造函数传参

    3.实例继承

    为父类实例添加新特性,作为子类实例返回

    function Cat(name){
      var instance = new Animal();
      instance.name = name || '';
      return instance;
    }
    var cat1 = new Cat('大毛')
    

    缺点
    1.实例是父类的实例,不是子类的实例
    2.不支持多继承

    4.拷贝继承

    把父对象的所有属性和方法,拷贝进子对象

      function Animal(){}
     Animal.prototype.species = "动物";
    
     function Cat(name){
         this.name = name;
      }
      function extend(Child, Parent) { 
         var p = Parent.prototype;
        var c = Child.prototype;
        for (var i in p) {
          c[i] = p[i];
          }
      }
    
    extebd(Cat, Animal)
    var cat1 = new Cat('大毛')
    alert(cat1.species)
    

    缺点:
    1.效率低,内存占用高(因为需要拷贝父类的属性)
    2.无法拷贝对象和数组

    5.组合继承
    通过调用父类构造,继承父类的属性并保留可以传参,然后通过将父类实例作为子类原型,实现函数复用

    function Animal(){ this.species = '动物'}
    function Cat(name){
       Animal.apply(this)
      this.name = name
    }
    Cat.prototype = new Animal()
    Cat.prototype.constructor = Cat
    var cat1 = new Cat('大毛')
    

    优点:
    1.可以继承实例属性和方法买也可以继承原形舒心个方法
    2.即是子类的实例,也是父类的实例
    3.可传参
    4.函数可复用
    缺点: 调用了两次父类构造函数,生成了两份实例

    寄生组合继承
    通过计生方式,去掉父类的实例属性,这样,在调用两次父类的构造函数的时候,就不会初始化两次实例

    function Cat(name){
      Animal.call(this)
      this.name = name 
    }
    (function(){
      //创建一个没有实例方法的类
      var Supe = function(){}
      Super.prototype = Animal.prototype
      //将实例作为子类的原形
      Cat.prototype = new Super()
      Cat.prototype.constructor = Cat
    }())
    
    var cat = new Cat('大毛')
    

    优点
    1.比起组合继承,减少了一次实例化父类,节省内存

    四、非构造函数的继承

    object()继承
    浅拷贝
    深拷贝

    1.objetc()继承
    实现objecy()函数,把子对象的prototype属性,指向父对象,使得父子对象连在一起

    function obejct(o){
      function F(){}
      F.prototype = o
      return new F()
    }
    var guangzhou = object(Chinese)
    

    2.浅拷贝
    把父对象的属性,全部拷贝给子对象,也能实现继承

    function copy(p){
      var c = {}
      for(var i in p){//[]则遍历牵引值 {}则遍历属性名
        c[i] = p[i]  
      }
      return c
    }
    

    3.深拷贝
    深拷贝,能够实现真正意义上的数组和对象的拷贝,只需要递归地调用浅拷贝

    function deepCopy(p,c){
      var c = c || {}
      for(var i in p){
        if(typeof i === 'object'){ //typeof arr && typeof object => object
        var c[i] = (p[i].constructor === Array) ? []: {}
        deepCopy(p[i], c[i])   
        }else{
          c[i] = p[i]
        }
      }
    return c
    }
    

    JS继承的实现方式

    相关文章

      网友评论

          本文标题:原型、原型链、继承(构造函数继承,非构造函数继承)

          本文链接:https://www.haomeiwen.com/subject/ilewfftx.html