原型繼承+原型鏈 + 對象繼承發展

1、原型繼承:閉包

  1、提及原型繼承,就要先由構造函數創造對象提及,首先了解構造函數內部基本原理:app

      (1).在函數體最前面隱式的加上this = {}函數

      (2).執行 this.xxx = xxx;this

      (3).隱式的返回thisspa

    而且要注意隱士建立的this對象中有個名爲__proto__的屬性,其屬性值爲該構造函數繼承的原型prototype。prototype

    而原型對象的有一個名爲constructor的屬性,其屬性值爲繼承之的構造函數,code

    因此能夠經過這兩個屬性相互查看對象

  2.原型的定義及一些特色:blog

    a.定義:原型是function對象的一個屬性,它定義了構造函數製造出的對象的公共祖先。經過該構造函數產生的對象,能夠繼承該原型的屬性和方法。原型也是對象。繼承

    b.利用原型特色和概念,能夠提取共有屬性。

 

    c.對象如何查看原型 — > 隱式屬性 __proto__

 

    d.對象如何查看對象的構造函數 — > constructor

  三、若一個構造函數沒有指定其原型,則其原型默認爲Object.prototype

2、原型鏈:

  1.原型的造成,最好的解釋就是代碼了,看以下代碼便可

  

A.protorype = {
        name: 'a'
    }
    function A() (
        this.name = 'A';
    )
    B.prototype = new A();
    function B() {
        this.name = 'B';
    }
    C.prototype = new B();
    function C(){
        this.name = 'C';
    }
    C繼承B,B繼承A,造成C->B->A的一條以原型爲繼承方式的原型鏈

 

 

  二、原型鏈上屬性的增刪改查:

    (1)查:優先去實例對象上尋找是否有該屬性,若沒有,則再去其對應的原型上去尋找該屬性,若都沒有,則返回undefined

    (2)增:直接給實例對象增添屬性,則僅僅在實例對象上增添屬性,若在原型上增添屬性,則在原型上增添屬屬性,則在原型上增添屬性,其實例繼承原型增添的屬性。

    (3)刪:delete僅僅能刪除實例對象的屬性,即構造函數原有的本身的屬性和後來實例對象增添的屬性,還有關於delete的一點需注意,delete沒法刪除原型的屬性和用var定義的變量(即非window的屬性)

      (4)改:更改實例對象的屬性,則僅僅更改實例對象的屬性值;更改原型的屬性值,則更改原型的屬性值,繼承該原型的對象對應屬性值也會被更改;

3、對象繼承的發展:

  一、傳統模式:即正常的經過構造函數建立實例對象,來繼承原型

    缺點:繼承了過多沒必要要的屬性

  二、借用其餘構造函數(即經過call / apply來改變構造函數內this對象的引用)

    缺點:沒法繼承借用構造函數的原型

    

  A.prototype = {
        name: 'a',
        age: 18,
        class: 1
    }
    function A(){
        this.name = 'A';
    }
    function B(){
        A.call(this);
    }
    var b = new B();
    console.log(b.name); // A
    console.log(b.age) // undefined

 

  三、共享原型:即將其餘構造函數的原型直接賦值給本構造函數的原型

    缺點:兩個原型會想回影響,更改其中一個原型,更一個對應的原型也會被更改。

  

  A.prototype = {
        name: 'a',
        age: 18,
        class: 1
    }
    function A(){
        this.name = 'A';
    }
    B.prototype = A.prototype;
    function B(){
        this.name = 'B';
    }
  C.prototype = A.prototype;
  function C() {
    this.name = "C";
  }
var a = new A(); var b = new B();
var c = new C(); console.log(a.age);
// 18 console.log(b.age); //18
console.log(c.age); //18

// 原型繼承成功 B.prototype.age = 20; //更改其中一個原型的age屬性 console.log(b.age);//20 console.log(c.age); //20 // 繼承A原型的B和C相互影響

 

  四、聖盃模式:

     每次繼承的都是新建立的F構造函數實例,相互之間不會影響。其實此處針對F造成了閉包,Child引用了F,致使F不會銷燬。

    (1)正常函數形式:

    

  function inherit (Child, Parent) {
        // 借用F這個中間量來繼承,而不是直接共享原型
        var F = function (){}
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        // 自定義構造函數原型時,同時要更正自定義原型的constructor,不然通常默認爲Object(),次函數若不指定constructor,則constructor爲Parent
        Child.prototype.constructor = Child; 
        
        Child.prototype.uber = Parent; //記錄真正繼承的是誰
    }

 

    (2)閉包形式:

    

    var inherit = (function(){
        var F = function (){};
        return function (Child, Parent) {
            F.prototype = Parent.prototype;
            Child.prototype = new F();
            Child.prototype.constructor = Child;
            Child.prototype.uber = Parent;
        }
    })();
相關文章
相關標籤/搜索