解析原型鏈

首先,建立一個構造函數:程序員

function Person(name,age){
        this.name=name;
        this.age=age;
        this.eat=function(){
            console.log("吃");
        }
    }

接着,咱們實例化兩個對象:瀏覽器

     var stu1 = new Person("小明",20);
     var stu2 = new Person("小花",30);

咱們調用兩個對象的eat方法:函數

    stu1.eat();
    stu2.eat();

  結果確定是:吃  吃this

可是:這兩個方法不是同一個方法spa

   console.log(stu1.eat===stu2.eat);//false

這是爲何呢?prototype

  每一個實例對象都有本身的eat方法,而這個eat方法不是共享的3d

 

若是我要建立100個對象,方法的實現是同樣的,但卻不能共享,豈不是很浪費空間?code

天無絕人之路,經過原型的方式是能夠解決的:
對象

  原型添加方法: blog

Person.prototype.eat=function(){
        console.log("吃東西");
    }

  此時構造函數和原型對象中都有eat方法,默認先找構造函數,構造函數沒有找原型對象,原型對象沒有undefind

  咱們刪掉以前構造函數中的eat(),此時:

   console.log(stu1.eat===stu2.eat);//true

  原型的做用:解決數據共享,節省內存空間

那麼原型對象是什麼呢?

  Person() 是一個構造函數,咱們經過console.dir(Person),查看他的詳細信息,

  

  發現該構造函數有一個屬性prototype,該屬性也是一個對象,標準屬性,是給程序員使用的,這個屬性叫作原型對象。

 

  stu1是一個實例對象,咱們經過console.dir(stu1),查看他的詳細對象

  

  發現該實例對象有一個屬性__proto__,該屬性也是一個對象,非標準屬性,給瀏覽器使用的,這個屬性叫作原型對象。

從stu1的詳細中看到他並無eat()方法,那麼他是如何訪問這個方法的呢?

  咱們打開prototype這個屬性:

  

  實例對象中沒有eat(),構造函數中的prototype中有eat()

  由此推出:實例對象的__proto__的指向和該實例對象所在的構造函數的prototype的指向相同,

       那麼實例對象就能夠直接訪問prototype中的方法了

下面圖中的construtor是什麼?

                                                                  

  上圖實例對象的__proto__中的constructor就是該實例對象所在的構造函數               構造函數中的prototype中的constructor指向的是原型對象所在的構造函數

而構造函數、實例對象、原型對象三者之間的關係是什麼呢?

  (1)實例對象是經過構造函數建立的

  (2)構造函數中prototype叫原型對象

  (3)構造函數中的prototype中有constructor叫構造器,指向的是該原型對象所在的構造函數

  (4)實例對象中__proto__叫原型對象

  (4)實例對象中__proto__指向的是該實例對象所在的構造函數的prototype

 

 

說到這裏咱們就要開始推導原型鏈了:

  能夠這麼理解:原型鏈就是實例對象和原型對象之間的一種關係

  咱們說:構造函數中有prototype,實例對象中有__proto__

      實例對象的__proto__指向的是該實例對象所在的構造函數中的prototype

  換句話說就是:對象的__proto__指向的確定是某個函數的prototype

  往下看:

  

  構造函數中prototype是對象,這個prototype中有__proto__也是對象,那麼這個__proto__指向的是誰呢?

    它指向的確定是某個構造函數的prototype

    此時,觀察它的構造器的指向----是Object()

    那麼得出結論:    

   Person.prototype.__proto__===Object.prototype//true

  

    繼續觀察Person():

    

    咱們以前說構造函數中有prototype,可是我此時也發現了構造函數中有__proto__,

    既然看到了__proto__,逆推思想:說明這個函數實際上也是一個對象(由於對象中有__proto__);

    因此Person()的__proto__指向的確定是其構造函數的prototype;

    對象是經過構造函數建立的,那麼Person()的構造函數又是誰呢?

      看Person.__proto__.constructor的指向--------Function()

    得出結論:   

   Person.__proto__===Function.prototype//true

    這個時候咱們知道了:

      js中的函數實際上都是經過Function這個構造函數來建立的(來實例化出來的);

    接下來,咱們往下深挖,Function

    

    由此推出:  

   Function.prototype.__proto__===Object.prototype//true

    

    由此推出:

   Function.__proto__=== Function.prototype;//true

    

    接下來,還有最後一個Object

    

      由此推出:   

    Object.__proto__=== Function.prototype;//true

      

      

    Object的prototype中沒有__proto__   

   Object.prototype.__proto__ === null;

 

總結原型鏈:

  

相關文章
相關標籤/搜索