ES5繼承模式

  果真,感受有些東西不整理一下仍是很容易忘記的,不少時候有須要不斷地去複習,感受JavaScript這門語言整體上不能算是特別難,可是知識點特別雜(坑也特別多...),感受最好仍是可以梳理出一個總體架構出來javascript

  好了,廢話很少說,今天大體上總結一下ES5中的繼承模式,大體上仍是參照《JavaScript高級程序設計》上來的。java

  1. 原型模式架構

     function Person (name, age) {
         this.name = name;
         this.age = age;
     }
     ​
     Person.prototype.sayName = function () {
            return this.name;
     }
        Person.prototype.sayAge = function () {
            return this.age;
        }
     ​
        function Student (name, age, school) {
            this.name = name;
            this.age = age;
            this.school = school;
        }
     ​
        Student.prototype = new Person();
        Student.prototype.saySchool = function () {
            return this.school;
        }
     ​
        let stu = new Student('zhang', 18, 'zust');
        console.log(stu.getName()); // 'zhang'
     ​

   以上的繼承方式是比較好理解的,當訪問Student實例的sayName()方法時,先遍歷實例方法(無匹配),再搜索函數

   原型對象Person實例(無匹配), 最後搜索Person.prototype對象上,獲得sayName()方法。優化

  1. 借用構造函數this

     function Person(name, age){
         this.name = name;
         this.age = age;
     }
     ​
     Person.prototype.sayName = function () {
         return this.name;
     }
     ​
     Person.prototype.sayAge = function () {
         return this.age;
     }
     ​
     function Student(name, age, school){
         Person.call(this, name, age);
         this.school = school;
     }
     ​

    所謂的借用構造函數是借用父類的構造函數來設置本身的屬性,進一步避免了代碼的重複。spa

    以上是單純使用了借用構造函數實現的繼承,能夠看到在子類中經過重用父類的構造方法爲子類設置屬性,可是僅僅使用借用構造函數,子類將沒法繼承父類構造函數原型中的方法。prototype

  2. 組合式繼承(原型模式與借用構造函數的組合)設計

     function Person(name, age){
         this.name = name;
         this.age = age;
     }
     Person.prototype.sayName = function () {
         return this.name;
     }
     Person.prototype.sayAge = function () {
         return this.age;
     }
     ​
     function Student(name, age, school) {
         Person.call(this, name, age);
         this.school = school;
     }
     ​
     Student.prototype = new Person();
     ​

    以上的繼承方式是原型模式和借用構造函數模式的組合方式,經過原型鏈的方式繼承父類構造函數原型對象上的方法,使用借用構造函數重用父類構造函數中的代碼。至關因而對於原型鏈繼承模式的優化,將父類構造函數中的代碼加以重用。對象

  3. 原型式繼承

     let sup = {name: 'zhang', age: 18};
     let extend = function (obj) {
         function F () {};
         F.prototype = obj;
         return new F();
     }
     ​
     let sub = extend(sup);
     console.log(sub.name);

    就以上的繼承方式而言,我的感受與如下實現方式並無太大區別

     let sup = {name: 'zhang', age: 18};
     let sub = {};
     Object.setPrototypeOf(sub, sup);
     console.log(sub.name);

    在子類對象建立的過程當中,全部的父類變量將會被子類共享,尤爲是引用類型的變量

     const sup = {name: 'zhang', age: 18, arr: ['a', 'b', 'c']}
     ​
     const extend = function (obj) {
         function F(){};
         F.prototype = obj;
         return new F();
     }
     const a = extend(sup);
     const b = extend(sup);
     console.log(a.arr); // ['a', 'b', 'c']
     b.arr.push('d');
     console.log(a.arr); // ['a', 'b', 'c', 'd']

    在原型上定義了一個引用類型的屬性arr,而後經過繼承建立兩個對象,經過對象b訪問arr屬性時,因爲對象b上並無arr屬性,所以,會訪問b的原型對象,也就是sup對象中的arr屬性,這是全部子類對象共享父類對象中的屬性的實質。

    ES5中經過Object.create()方法實現原型式繼承的標準API

  4. 寄生式繼承

     function createPerson (obj) {
         var clone = Object.create(obj);
         clone.getName = function () {
             return this.name;
         }
         return clone;
     }
     ​
     var person = {name: 'zhang', age: 18};
     var p = createPerson(person);
     console.log(person.name); // 'zhang'

    寄生式繼承是將原型式繼承以及增長實例方法這兩個步驟封裝成一個工廠函數,而後將生成的對象返回

    代碼仍是比較簡單的,可是具體是幹嗎用的,emmmmmm...因此,再也不贅述

  5. 寄生組合式繼承

     function Person (name, age) {
         this.name = name;
         this.age = age;
     }
     ​
     Person.prototype.getName = function () {
         return this.name;
     }
     ​
     Person.prototype.getAge = function () {
         return this.age;
     }
     ​
     function Student (name, age, school) {
         Person.call(name, age);
         this.school = school;
     }
     ​
     Student.prototype = Object.create(Person.prototype);
     Student.prototype.getSchool = function () {
         return this.school;
     }

    這種繼承方式能夠看作是組合式繼承的優化,咱們能夠看到,其實這種方式與組合式繼承其實並無太大區別,區別僅僅在於設置Student.prototype的方式不一樣。組合式繼承是經過new Person()的方式產生一個原型對象,而寄生組合式繼承是經過Object.create()方法產生一個通過淺複製獲得原型對象的一個副本。

相關文章
相關標籤/搜索