• 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);

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

  • 相关阅读:
    django 标签的使用
    django(models)视图与html 简单的操作
    Django 简单的使用
    安全性测试计划
    常用缩写
    ADB 基本命令整理
    kindle升级测试
    虚拟机的类加载机制
    垃圾收集器与内存分配策略之篇三:理解GC日志和垃圾收集器参数总结
    垃圾收集器与内存分配策略之篇二:垃圾收集器
  • 原文地址:https://www.cnblogs.com/maoxiaodun/p/10007759.html
Copyright © 2020-2023  润新知