zoukankan      html  css  js  c++  java
  • js之继承

    js中的继承有多种方式,因为其不像java一样有可以直接类继承(es6 中扩展了extend),他用的是原型链继承

    首先我们来构造一个动物的父类

    function Animal (name = 'Animal'){
                this.name = name;
                this.play = function(){
                    console.log( this.name+"can play");
                }
            } // 定义了name 属性和play方法
            Animal.prototype.say = function(){
                console.log("hello,i can speak Animal language")
            } // 在原型链上挂载了 say 方法

     在该父类中我们有一个play的实例私有方法和一个say方法,该方法为原型链共享方法,所有的实例都可以修改该方法。

    1.原型继承,将子类的原型指向父类的实例,这样子类的实例就可以通过原型链去继承父类的方法以及属性

            function Cat(){}        
            Cat.prototype = new Animal();
            Cat.prototype.name = 'lowcat';
            
            var cat = new Cat(); 
            console.log(cat.name); //输出lowcat
            console.log(cat.say()); //输出 hello, i can speak Animal language
            console.log(cat.play()); //输出 lowcat can play
            console.log(cat instanceof Animal); // true
            console.log(cat instanceof Cat); // true

    优点 1. 非常纯粹的继承关系 实例是子类的实例 也是父类的实例
     2. 父类新增原型方法/原型属性 子类都能访问到
     3. 简单
     缺点 1.要想为子类新增原型属性和方法,必需要在new Animal()语句执行之后 (因为先要把原型指向搞清楚)
     2.无法实现多继承
     3.来自原型的所有属性被所有实例共享
     4.创建子类实例时,无法想父类构造函数传参(因为直接执行父类的构造函数)

    2.构造继承(使用call函数改变当亲父类的上下文)

             function Dog(name = 'pony'){
                 Animal.call(this);
                 this.name = name ;
             }
             var dog = new Dog("tony");
             console.log(dog.name); //输出tony
             console.log(dog.play());// 输出 i can play
    console.log(dog.say()); 输出错误 console.log(dog instanceof Animal); //false console.log(dog instanceof Dog); // true

    优点 :1. 解决了原型继承中所有子类实例共享父类的属性与方法
     2. 创建子类实例是,可以向父类传递参数
     3. 实现了多继承
     缺点 :1.实例斌不是父类的实例,只是子类的实例
     2.只能继承父类的实例属性和方法,不能继承原型属性方法
    3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
     此继承方式使用了call函数 改变当前子类构造函数的运行环境,所有子类能够访问到父类的方法,但却不能访问原型链,因为在原型链上并没有实质的改变;
    三、工厂模式继承(内部使用obj直接作为父类的实例,然后return 回去当作子类的实例)

    function Fish (name = "fish") {
                 var obj = new Animal();
                 obj.name = name;
                 return  obj;
             }
             var fish = new Fish("fish");
             console.log(fish.name); //输出 fish
             console.log(fish.play()); // 输出 i can play
             console.log(fish.say()); // 输出hello ,i can speak Animal lanvuage
             console.log(fish instanceof Animal);// true
             console.log(fish instanceof Fish); //true

    优点: 1.不限制调用方式,不管是new 还是直接调用 返回的对象具有相同的效果
     缺点:1.实例是父类的实例,不是子类的实例
                2.不支持多继承

    四、拷贝继承

                function Mouse(name ="mouse"){
                  var animal = new Animal();
                  for(var p in animal){
                      Mouse.prototype[p] = animal[p];
                  }
                  Mouse.prototype.name = name;
              }
             var mouse = new Mouse("Jack");
             console.log(mouse.name); // Jack
             console.log(mouse.play()); // i can play
             console.log(mouse.say()); // hello, i can speak Animal language
             console.log(mouse instanceof Animal); //ture
             console.log(mouse instanceof Mouse) // ture

    优点 1.支持多继承 (多复制几个父类)
     缺点 1.效率低,用了遍历copy(内存占用高)
              2.无法获取父类的不可枚举方法(在对象中的atrributes object(属性描述对象)可以设置对象属性的状态)

    五、寄生组合继承(首先将父类的上下文拿到子类当中,在将子类的原型指向父类的原型,这里并不是直接指向)

    function Bird(name ="bird"){
                   Animal.call(this);
                   this.name = name;
               }
               (function(){
                     var Obj = function(){}; // 首先创建一个空对象
                     Obj.prototype = Animal.prototype; // 将空对象的原型指向父类的原型
                     Bird.prototype  = new Obj(); // 将子类的原型指向 空对象的实例,见解继承了父类的原型
                     Bird.prototype.constructor = Child; // 因为此时obj的原型的constrcutor指向了obj的构造函数,手动修复指向
               })();
              var bird = new Bird();
             console.log(bird.name);
             console.log(bird.play());
             console.log(bird.say());
             console.log(bird instanceof Animal);
             console.log(bird instanceof Bird);

    这个方法十分完美,解决了组合继承的两次实例化问题

  • 相关阅读:
    poj3669 广搜
    检索所有课程都选修的的学生的学号与姓名
    UVA10160 Servicing Stations
    uva11205 The broken pedometer 子集生成
    poj1101 the game 广搜
    poj3009 Curling 2.0 深搜
    poj 1564 Sum It Up 搜索
    HDU 2268 How To Use The Car (数学题)
    codeforces 467C George and Job(简单dp,看了题解抄一遍)
    HDU 2267 How Many People Can Survive(广搜,简单)
  • 原文地址:https://www.cnblogs.com/maoxiaodun/p/10007759.html
Copyright © 2011-2022 走看看