Javascript之傻傻理不清的原型鏈、prototype、

Javascript之傻傻理不清的原型鏈、prototype、__proto__

新人學習Javascript,其中的原型鏈一直是雲裡霧裡,不得要領,查了很多相關資料,覺得這遍講得最為清晰易懂,特轉載分享,共同學習。

1. JavaScript內置對象

所謂的內置對象 指的是:JavaScript本身就自己有的對象 可以直接拿來就用。例如Array String 等等。JavaScript一共有12內置對象

其中10個函數類型( String,Number,Boolean,Array,Function,Date,RegExp,Error,Object,Event )函數類型 有 __proto__和 prototype 屬性

2個對象類型(Math,JSON) 對象類型只有__proto__屬性

下面有一張圖片 由蘇仔提供。

Javascript之傻傻理不清的原型鏈、prototype、__proto__

2. 感性認識JS裡的“德羅斯特效應”之原型鏈

打開瀏覽器的控制面板,隨便輸入一個JS內置的構造器函數,比如Array,控制檯輸出的是一個名為Array的函數體,這好像並沒有什麼稀奇的,但是,當你接著輸入Array.prototype,控制面板輸出了一堆我們經常用到的Array構造器的方法,把目光轉移到最下方,有一個叫__proto__的屬性,好奇的點開。列表列出的不是Object構造器的方法麼,裡邊有我們非常熟悉的hasOwnProperty還有toString等方法。如果Array是構造器,那麼控制面板輸出的Array.prototype的所有屬性中constructor又是什麼構造器?點開看看,之後就像身處德羅斯特效應中一樣,__proto__和constructor,還有Array構造器中常用的方法名不斷的出現,一層套一層,一層層展開,沒有盡頭。。。

怎麼證明 你是你?

拿Array舉例,Array.prototype中有一個constructor屬性,這個屬性的值就是Array構造器自己。 所以我在console裡面測試

(每一個構造函數都有)

Javascript之傻傻理不清的原型鏈、prototype、__proto__

2、“遺傳進化鏈__proto__”,怎麼證明一切皆對象?

所有的JS內置構造器都本是對象。可是從什麼線索開始向過去前進呢,原型鏈(我給他起了一個名字叫遺傳進化鏈)就是突破口。所有JS構造器(當然不止構造器有)都有一個__proto__屬性,這是原型鏈指針,指向遺傳進化成它的“那個”它“遺傳”了“那個”的特性,而又進化出了它自有的特性

Javascript之傻傻理不清的原型鏈、prototype、__proto__

這裡Array 是內置對象且是函數類型。所以Array有__proto__屬性 指向的是函數類型 (function(){})。所以當我們在輸出Array.__proto__.proto__;就會返回對象類型(Object{}).但是再向上就null。因為Object就是父類了。所有的繼承自Object。

JS內置構造器其中之一的Array原本就是一個函數,而這個函數就是Function的prototype,所以Function.prototype有的方法,JS內置構造器都有,比如call()、apply()、bind()等(其實我們自定義的函數也是繼承自Function.prototype,所以我們自己也可以定義構造器)。而Function.prototype的進化鏈指針又指向了Object.prototype。

3、怎麼證明到頭來一切都是空?

Javascript之傻傻理不清的原型鏈、prototype、__proto__

4、怎麼證明所有JS內置構造器和自定義函數都是Function構造器的原型(prototype)。

10個函數類型構造器的進化鏈指針__proto__指向Function構造器的原型.

Javascript之傻傻理不清的原型鏈、prototype、__proto__

這裡需要注意所有構造器的prototype都是對象(object)類型,只有Function.prototype是函數(function)類型,這是為了保證函數構造器們的__proto__指向的都是函數

3. JSON和Math

JS內置的構造器函數都可以使用new關鍵字實例化一個對象,我們稱實例化後的這個對象就是某某構造器的一個實例。就像我們每一個“人”都是“人類”這個構造器函數的一個實例。

Javascript之傻傻理不清的原型鏈、prototype、__proto__

我們試試JSON 和Math 能不能實例化對象。

Javascript之傻傻理不清的原型鏈、prototype、__proto__

不可以。JSON和Math不是構造器函數,他們是普通的對象。

只有構造器函數才能使用new 關鍵字實例化一個對象,而JSON和Math已經是對象了,所以我們可以不用實例化直接使用JSON和Math中的屬性和方法~~(我們實例化的目就是想用實例化後的對象裡的屬性和方法,那麼既然JSON和Math已經是對象了,就省去實例化的操作 直接使用靜態方法。

所以JSON和Math不屬於10個構造器函數,但他們12個共同屬於Javascript的內置對象。

4. __proto__進化鏈指針設計為什麼如此重要

javascript中為什麼會有__proto__原型鏈的設計。

先實例化一個String對象並將其賦值給str這個變量,然後我們輸出這個str

Javascript之傻傻理不清的原型鏈、prototype、__proto__

從str輸出的內容來看,str有四個屬性,分別是0、1、2、length。

但是 str.charAt(0); // l

str裡面沒有charAt()方法 但是沒有報錯。這是因為str的進化鏈上存在這個屬性方法,那麼charAt()這個方法在進化鏈的那個節點上呢。

Javascript之傻傻理不清的原型鏈、prototype、__proto__

原來String.prototype擁有charAt這個方法,而str的__proto__指針指向String.prototype。str.__proto__.__proto__指向的對象所擁有的屬性str也都可以直接用

看到str.__proto__.__proto__指向的對象所擁有的屬性中有一個hasOwnProperty屬性方法了麼,str可以直接使用這個屬性方法 在驗證之前先說下str.__proto__.__proto__指向了誰?指向的是Object的prototype屬性。

Javascript之傻傻理不清的原型鏈、prototype、__proto__

Object.prototype.hasOwnProperty()屬性方法用來檢驗一個對象是否自己擁有一個屬性而非通過進化鏈__proto__繼承來的屬性

Javascript之傻傻理不清的原型鏈、prototype、__proto__


分享到:


相關文章: