JS面向對象之二 【原型鏈】(對象和對象之間的關係)

JS面向對象之二 【原型鏈】(對象和對象之間的關係)

注意這個系列文章,要常常站在JS之父的視角去思考。數組

牢記咱們的需求,我要在JS沒有class的狀況下,那麼利用JS現有的東西,搞出相似class的東西。瀏覽器

回一下JS有什麼? 有7種數據類型:函數

  • 6個基本數據類型 : string number boolean null undefined symbol
  • 1個引用類型 : obj (你須要知道前6個基本數據類型是存儲在棧中的, 1個引用類型obj存儲是的引用,它的值存儲在堆中的.)

對象分紅3類: 普通對象 、數組對象 、函數對象。spa

思考問題1: 咱們都知道array function都屬於object,那麼既然他們都是對象,必定有某些相同之處吧,對象和對象之間有什麼關聯呢?prototype

若是說你沒有思考過這個問題,那麼能夠換一個更具體的問題。設計

思考問題2: 打印這段代碼,到瀏覽器控制檯,你會發現咱們空對象,"自帶"了一個toString()?code

var obj = {
    name: 'ziwei',
    sex : '男',
    eat : function(){}
}
obj.toString()

問題1: array funciton obj 都是對象,那麼爲何說他們都是對象,經過什麼關聯起來的?對象

問題2: 爲何一個空對象,"自帶"toString()方法?繼承

若是你不清楚以上問題的答案,恭喜你,這篇文章的主題【原型鏈】就能夠清楚的解答你的疑惑。圖片

原型鏈

什麼場景下,須要原型鏈。

仍是上面這段代碼

var obj = {
    name: 'ziwei',
    sex : '男',
    eat : function(){}
}
obj.toString()

若是咱們想本身實現,讓obj,具備toString()怎麼辦? 直覺確定是添加在obj上咯。

這樣由於toString(),是函數對象,因此須要在內存中開闢一塊空間,存放toString()

如今,咱們要聲明100個obj對象,他們都須要具有toString()怎麼辦?

若是循環100次給每一個obj都添加toString(),須要在內存空間開闢100個空間,存在100個相同的toString(),勢必形成內存空間的浪費,在JS被創造時,內存仍是十分寶貴的資源。

因此JS之父想出一個辦法。把對象須要共享的屬性和方法,放到一個內存空間裏,而後每個對象都有一個屬性都指向這一個空間。

因此原型鏈被髮明,最樸素的想法就是節省內存空間。

JS裏如何設計原型鏈規則的呢?

1.全部對象都有的這個屬性長得很奇怪,叫作 proto

var obj = {}
console.log(obj.__proto__ )  訪問,你就能夠查看全部object都共享的屬性。

2.這個__proto__所指向的那塊內存空間裏的屬性,並非在var obj = {}時,才被添加進去的,而是一直都存在的。

經過 window.Object.prototype  你一樣能夠訪問到這個共享的內存空間

3.__proto__裏面還能夠有__proto__,畢竟被稱爲原型鏈嘛。

之因此須要"鏈",你能夠看這樣一個例子

var arr = []
數組做爲一個數組是有push()方法的, 但是咱們查看 window.Object.prototype裏並無共享push方法

咱們爲了實現數組有push方法,可是不能讓全部的對象都有push方法,爲了實現這個需求,JS是這樣設計的。

clipboard.png

JS另外開闢了一個內存空間,用來專門存儲數組的共有方法和屬性。你能夠用過window.Array.prototype來訪問它

這樣JS數組,arr經過__proto__繼承了Array.prototype的方法,有經過Array.prototype.__proto__繼承了Object.prototype上的訪問。

相似的咱們訪問obj.name時,JS會在obj內部尋找name屬性,若是沒有,就會到__proto__中去尋找name,一直到Object.prototype若是仍是沒有name,就會返回undefined

因此這種依靠原型來繼承的方式,很想一個鏈條,一層一層的向上尋找,因此叫作原型鏈,原型鏈的頂端就是Object.prototype

最後回答文章最初的2個問題:

問題1: array funciton obj 都是對象,那麼爲何說他們都是對象,經過什麼關聯起來的?

他們就是經過__proto__關聯的。
Array.prototype.__proto__ 繼承了 Object.prototype
Function.prototype.__proto__ 繼承了 Object.prototype

他們同根同源,都繼承自Object.prototype,數組只是比普通的對象多了一些方法,因此他們都是對象唄

![圖片上傳中...]

問題2: 爲何一個空對象,"自帶"toString()方法?

由於全部對象都自帶__proto__屬性,這個屬性指向Object.prototype這個內存空間。

由於Object.prototype存儲着有toString(),因此全部對象都有。

相關文章
相關標籤/搜索