《javascript高等程序设计》 继续完成体式格局

这篇原本应该是作为写JS 面向对象的前奏,只是作为《javascript高等程序设计》继续一章的笔记

  • 原型链

    • code 完成

      function SuperType() {
        this.colors = ['red','blue', 'green'];
      }
      function SubType() {
      }
      SubType.prototype = new SuperType();
      var instance1 = new SubType();
      instance1.colors.push("black");
      console.log(instance1.colors); // ['red','blue', 'green','black']
      
      var instance2 = new SubType();
      console.log(instance2.colors); // ['red','blue', 'green','black']
      
      var instance = new SuperType();
      console.log(instance.colors); // ['red','blue', 'green']
    • 运用原型链来完成继续,原型现实上会变成另一个范例的实例,因而,本来的实例属性,会变成如今的原型属性了
    • 在建立子类的实例时,不能向父类的组织函数中通报参数
  • 借用组织函数

    • code 完成继续

      function SuperType() {
        this.colors = ["red","blue","green"];
      }
      function SubType() {
        SuperType.call(this);
      }
      
      var instance1 = new SubType();
      instance1.colors.push("black");
      console.log(instance1.colors); // ["red", "blue", "green", "black"]
      
      var instance2 = new SubType();
      console.log(instance2.colors); // ["red", "blue", "green"]
      
      var instance = new SuperType();
      console.log(instance.colors); // ['red','blue', 'green']

    一样也可以完成参数的通报

    function SuperType(name) {
      this.name = name;
    }
    function SubType(){
      SuperType.call(this, "jack");
      this.age = 29;
    }
    
    var instance = new SubType();
    console.log(instance.name); // jack
    console.log(instance.age); // 29
    • 假如仅仅是借用组织函数,那末将没法防止组织函数情势存在的题目–要领都在组织函数中定义,因而,函数复用也就无从谈起了。而且,在超范例的原型中定义的要领,对子类而言也是不可见的,效果一切范例都只能运用组织函数情势。
  • 组合继续

    • 将原型链和借用组织函数的手艺组合到一块,从而发还两者之长的一种继续情势。其背地的思绪是运用原型链完成对原型属性和要领的继续,而经由历程借用组织函数来完成对实例属性的继续。如许,即经由历程在原型上定义要领完成了函数复用,又可以保证每一个实例都有它本身的属性。
    • code 完成

      function SuperType(name) {
        this.name = name;
        this.colors = ['red','blue','green'];
      }
      SuperType.prototype.sayName = function() {
        console.log(this.name);
      };
      function SubType(name, age) {
        SuperType.call(this, name);
        this.age = age;
      };
      
      SubType.prototype = new SuperType();
      SubType.prototype.sayAge = function(){
        console.log(this.age);
      };
      
      var instance1 = new SubType("jack", 29);
      instance1.colors.push("black");
      console.log(instance1.colors); //["red", "blue", "green", "black"]
      instance1.sayName(); // jack
      instance1.sayAge(); // 29
      
      var instance2 = new SubType("allen", 23);
      console.log(instance2.colors); // ["red", "blue", "green"]
      instance2.sayName(); //allen
      instance2.sayAge(); // 23
    • instanceOfisPrototypeOf 也可以用于辨认基于组合继续建立的对象
  • 原型式继续

    • 没有严厉意义上的组织函数,经由历程借助原型,可以基于已有的对象建立新对象,同时还没必要因而建立自定义范例

      function object(o){
        function F(){};
        F.prototype = o;
        return new F();
      }

    object() 函数内部,先建立了一个暂时性的组织函数,然后将传入的对象作为这个组织函数的原型,末了返回这个暂时范例的一个新实例。从实质大将,object() 对传入个中的对象执行了一次浅复制

    function object(o) {
        function F() {};
        F.prototype = o;
        return new F();
    }
    
    var person = {
        name:'jack',
        friends:['allen','lucy','van']
    }
    
    var anotherPerson = object(person);
    anotherPerson.name = 'bob';
    anotherPerson.friends.push('steve');
    
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = 'linda';
    yetAnotherPerson.friends.push('shelly')
    
    console.log(person.friends); //["allen", "lucy", "van", "steve", "shelly"]

    这类原型式继续,请求你必须有一个对象可以作为另一个对象的基本。假如有这么一个对象的话,可以把他通报给object() 函数,然后再依据详细需求对获得的对象加以润饰即可。

    ECMAScript5 经由历程Object.create() 要领范例花了原型式继续。这个要领接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义分外属性的对象。在传入一个参数的情况下,Object,create()object() 函数要领的行动雷同

    在没有必要建立组织函数,而只是想让一个对象与另一个对象坚持相似的情况下,原型式继续是完全可以胜任的。不过,包括援用范例值的属性一直都邑同享相应的值,就像运用原型情势一样

  • 寄生式继续

    • 寄生式继续是与原型式继续严密相干的一种思绪。寄生式继续的思绪与寄生组织函数和工场情势相似,即建立一个仅用于封装继续历程的函数,该函数在内部已某种体式格局来加强对象,末了再像真的是它做了一切事情一样返回对象。

      function createAnother(original){
        var clone = object(original); // 经由历程挪用 object() 函数建立一个新对象
        clone.sayHi = function(){  // 以某种体式格局来加强对象
          alert("hi");
        };
        return clone; // 返回这个对象
      }
    • 在重要斟酌对象而不是自定义范例和组织函数的情况下,寄生式继续也是一种有效的情势。前面树模继续情势时运用的object() 函数不是必须的;任何可以返回新对象的函数都运用与此情势。
  • 寄生组合式继续

    • 组合继续是JavaScript 最经常使用的继续情势;不过也有本身的不足。组合继续最大的题目就是无论什么情况下,都邑挪用两次父类的组织函数:一次是在建立子类原型的时刻,另一次是在子类组织函数内部。

    子类最终会包括父类对象的悉数实例属性,但我们不得不在挪用子类组织函数时重写这些属性。

    function SuperType(name) {
        this.name = name;
        this.colors = ['red','blue','green'];
    }
    
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    }
    
    function SubType(name, age) {
        SuperType.call(this, name); // 第二次挪用 SuperType()
        this.age = age;
    }
    
    SubType.prototype = new SuperType(); // 第一次挪用 SuperType()
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function() {
        console.log(this.age);
    };

    第一次挪用SuperType 组织函数时,SubType.prototype会获得两个属性:namecolors,他们都是SuperType 的实例属性,只不过如今位于SubType 的原型中。当挪用SubType 组织函数时,又会挪用一次SuperType 组织函数,这一次又在新对象上建立了实例属性namecolors。 因而,这两个属性就屏障了原型中的两个同名属性。

    所谓寄生组合式继续,即经由历程借用组织函数来继续属性,经由历程原型链的混成情势来继续要领。其背地的基本思绪是:没必要为了指定子类的原型而挪用父类的组织函数,我们所须要的不过就是父类原型的一个副本罢了。实质上,就是运用寄生式继续来继续父范例的原型,然后再将效果指定给子类的原型。寄生组合式继续的基本情势以下

    function inheritPrototype(subType, superType) {
      var prototype = object(superType.prototype);
      prototype.constructor = subType;
      subType.prototype = prototype;
    }

    第一步是建立父类原型的一个副本,第二步是为建立的副本增加constructor 属性,从而填补因重写原型而落空的默许的constructor 属性。第三步是将新建立的对象(即副本)赋值给子类的原型。

    function SuperType(name) {
        this.name = name;
        this.colors = ['red','blue','green'];
    }
    
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    }
    
    function SubType(name, age) {
        SuperType.call(this, name); // 第二次挪用 SuperType()
        this.age = age;
    }
    
    inheritPrototype(SubType, SuperType)
    SubType.prototype.sayAge = function() {
        console.log(this.age);
    };

    这个例子的高效率体如今它只挪用了一次SuperType 组织函数,而且因而防止了在SubType.prototype 上建立没必要要的、过剩的属性。于此同时,原型链还能坚持稳定;因而,还可以一般运用instanceofisPrototypeOf() 。开发人员普遍认为寄生组合继续是援用范例最理想的继续范式。

优缺点

  • 原型链会修正父类的属性,在建立子类的实例时,不能向父类的组织函数中通报参数
  • 借用组织函数,则没有继续
  • 组合继续(原型继续+借用组织函数) 组合继续最大的题目就是无论什么情况下,都邑挪用两次父类的组织函数:一次是在建立子类原型的时刻,另一次是在子类组织函数内部。
  • 原型式继续,请求你必须有一个对象可以作为另一个对象的基本,
    包括援用范例值的属性一直都邑同享相应的值,就像运用原型情势一样
  • 寄生式继续
    在重要斟酌对象而不是自定义范例和组织函数的情况下,寄生式继续也是一种有效的情势
  • 寄生组合式继续 (这是最成熟的要领,也是如今库完成的要领)
    第一步是建立父类原型的一个副本,第二步是为建立的副本增加constructor 属性,从而填补因重写原型而落空的默许的constructor 属性。第三步是将新建立的对象(即副本)赋值给子类的原型。

JS面向对象系列

    原文作者:catchonme
    原文地址: https://segmentfault.com/a/1190000010446190
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞