zoukankan      html  css  js  c++  java
  • js实现的几种继承方式

    他山之石,可以攻玉,本人一直以谦虚的态度学他人之所长,补自己之所短,望各位老师指正! 拜谢

    js几种继承方式,学习中的总结:

    所谓的继承是为了继承共有的属性,减少不必要代码的书写

    第一种:借用构造函数继承 :可以继承实例属性。但是原型中的方法无法继承

            // - 设置需要被继承的构造函数Animal
            function Animal(name,age){
                this.name = name;
                this.age = age;
            }
    
    
            Animal.prototype.eat = function(){
                console.log("吃各种吃的");
            };
    
            //再设置一个猫咪构造函数
    
            //思考:已经存在的构造函数Animal中具有了一些属性和方法,这些属性与方法时Cat构造函数需要的
            //      没有必要再书写一遍了,可以使用继承的方式获取
            function Cat(name,age){
                //通过call的方式,修改Animal中的this指向为当前Cat的this,并设置参数
                Animal.call(this,name,age);
            }
    
            var c1 = new Cat("jack",18);
            console.log(c1);

    第二种:原型继承  

    1 好处:可以继承原型中的方法
    2 缺点:①实例属性虽然有,但是无法传参(跟没有一样)
          ②要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行 否则会被覆盖
          ③无法实现多继承
          ④需要重新设置被覆盖的constructor属性 让constructor重新指向Cat
        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 c1=new Cat();
          console.log(c1);
          console.log(c1.name)//jack
          console.log(c1.age)//18
      通过原型链的方法可以查找到属性,但是无法传参
    原型链:查找规则,优先查找自身,如果没有则查找__proto__中是否存在; 原型链是用来描述实例对象与原型对象之间关系的一种方式。

    第三种:组合继承

     使用前面两种继承方式时发现各有优缺点,所以将两种方式结合即可
     这种结合使用的方式称为组合继承,组合继承是最常用的一种继承方式。   
         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 c1 = new Cat("rose",20,"red"); console.log(c1);
    在这总结一下原型链:

    原型链:查找规则,优先查找自身,如果没有则查找__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;
            }
    
            //原型继承方式中希望获取到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 c1 = new Cat("rose",20,"red");
            console.log(c1);

    第五种:拷贝继承 

    使用继承的原型中的方法时,查找的次数会降低
    效率较低,内存占用高(因为要拷贝父类的属性)
        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 c1 = new Cat("rose",20,"red");
            console.log(c1);
     

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

      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); 
  • 相关阅读:
    Linux学习之网络基础
    C# 随笔
    最牛B的编码套路
    c++ Primer 第七章不熟悉知识点总结
    oracle求表的倒数二行数据
    c++ Primer 第六章不熟悉知识点总结
    c++ Primer 第五章不熟悉知识点总结
    c++ Primer 第四章不熟悉知识点总结
    c++ Primer 第三章不熟悉知识点总结
    骑驴找马
  • 原文地址:https://www.cnblogs.com/shengmo/p/8634767.html
Copyright © 2011-2022 走看看