javascript學習筆記(17)--prototype

引入

javascript的原型繼承其實是比較麻煩的,涉及的東西挺多的…網上的都挺散的
上一節簡單的講了一下原型和創建對象,最後講了下原型鏈,原型鏈裏面有個關鍵字prototype
這個之前可能一直都沒有關注過,但他其實一直潛伏在javascript裏面
比如說我們這個簡單的數組,不知道你有沒有打開那個看看,下面會有一項prototype
在這裏插入圖片描述

什麼是prototype

prototype
原型;雛形;最初形態
在這裏我們取原型的意思
原型這個概念可能很好理解,可以理解爲就是模板,其他的都是靠這個模板復刻的,剛好這個也很像類的概念,這個原型就類似於一個class, 由他可以創造出一個個實例
這就是我們Array的原型,也就是上面那張圖裏下面的prototype
在這裏插入圖片描述可以看到,這裏面有很多很多的函數,結合上節的內容,通過原型繼承可以獲得原型的函數,所以我們纔會有a.shift()等等操作,其實都是通過訪問原型實現的

細心的同學可以發現,在最下面,還有一個原型,那這個原型又是什麼呢
在這裏插入圖片描述在這裏插入圖片描述展開Array.prototype可以發現他的內容其實和Object.prototype是一致的,而且Object.prototype下面沒有prototype了

prototype的作用

首先prototype可以體現並追溯原型鏈
我們通過展開對象,可以看到他的prototype,也就是對應着他的原型
注意,只有object和function可以查看prototype,其他的無法查看
在這裏插入圖片描述Object.prototype是最上層的原型,所有的原型都會指向這個原型,Object.prototype也是構成這個js世界的基石
同時通過prototype也可以查看我們到底繼承了哪些東西,可以使用哪些方法

上面這些只是剛剛熱身,下面纔是真正的燒腦

更深層次

我們之前創造一個數組都是使用的

var a=[1,2,3]

但實際上,他是這個函數的縮寫

var b=Array([1,2,3])

我們是通過調用Array這個函數來創建這個數組的
口說無憑,憑什麼他們一樣
有些同學可能會想到,那我可以用==來判斷他們是否一樣呀

誤區,==和===的使用
number,string,bool,undefiend這4種類型可以直接用==比較是否相等,判斷原理是根據他們的值來判斷,值一樣就是相等(函數沒有比較意義,就排除了)
然而對於object和function, ==和===比較的時候實際在比較他們地址,(因爲object和function本身過於複雜)
我們以爲通過==可以比較兩個object屬性和值,但實際上是他們的地址,所以無法用這個==的方法判斷object是否一直需要我們自己設計函數實現
在這裏插入圖片描述
但實際上兩個是一樣的
在這裏插入圖片描述

不過上面不是今天的重點,重點是要引入Array這個函數
在這裏插入圖片描述
這個就是我們的Array,這裏出現了兩個porototype,一個是灰色,一個是藍色
灰色的剛纔我們已經見過,他是指向上級原型的,它實際上顯示的是上級原型的prototype,這裏也就是Object.prototype(Array.prototype的上級)
而藍色對應的是這個函數本身具有的prototype

首先解釋第一個問題
什麼樣的對象有prototype
這裏專指藍色的
在這裏插入圖片描述在這裏插入圖片描述其實這麼多javascript對象裏,只有function有自己的原型
爲什麼
這不得不要提到爲什麼需要prototype
這就涉及到函數

私有
之前我們講過函數作用域,在函數內定義的變量和函數如果不對外提供接口,那麼外部將無法訪問到
在這裏插入圖片描述
我們在函數內部定義了b變量和s函數,只能在函數內部使用,外部和函數的實例仍然無法訪問這些變量和函數
上面這種變量稱爲私有變量

靜態
當定義一個函數後通過 “.”爲其添加的屬性和函數,通過對象本身仍然可以訪問得到,但是其實例卻訪問不到,這樣的變量和函數分別被稱爲靜態變量和靜態函數
在這裏插入圖片描述
注意,靜態變量前不能用var不然會報錯
在這裏插入圖片描述
其次,函數執行後靜態變量纔有效果

在這裏插入圖片描述
其實個人感覺吧,靜態變量和私有變量效果差不多,只不過第二種定義有點屬性的感覺
外部無法訪問靜態變量,實例化的對象也無法訪問函數的變量

實例
在面向對象編程中除了一些庫函數我們還是希望在對象定義的時候同時定義一些屬性和方法,實例化後可以訪問
在這裏插入圖片描述
在這裏插入圖片描述
可以看到,這樣定義其實比較尷尬,因爲我們的函數是在window下面,所以調用的時候其實他指向的是我們的window,而我們window又沒有繼承我們的函數,所以其實我們這樣實例化的結果是我們不能再訪問我們的變量了(區分開之前的靜態變量,靜態變量綁定了this,這個沒有綁定this)
而我們實例化之後,相當於繼承了函數的屬性,而且this分別綁定到了自己上面,互不干擾,我的屬性修改跟你的沒關係,最開始繼承的結果是我們函數內部定義的初始化值(這也可以解釋爲什麼私有變量和靜態變量無法訪問,因爲this綁定的問題,不可以越界)
但這樣有個缺點,就是缺少協同性,相當於我們彼此互不干擾,都是複製的結果,如果我們的方法出了錯,想要去修改,還必要修改每一個實例

prototype
爲了解決以上種種麻煩,prototype運營而生
在這裏插入圖片描述可以看到,實例化的對象可以直接訪問到prototype的值,而函數還是要先執行一下才可以訪問到,然後通過push追加的方式也可以實現共享,修改了prototype的值也會傳遞
在這裏插入圖片描述
但是要注意,如果直接修改實例化對象的值則不行

在這裏插入圖片描述
在這裏插入圖片描述這個其實好理解,還是跟共享的原理有關係
之前可以同步是因爲我們實例化對象裏其實上面屬性和值都沒有,當我們執行t2.a,t1.a的時候實際上是在訪問prototype.a,所以可以做到同步
而我們一旦執行了t1.a=1;相當於就給t1增加了個屬性a:1,這個時候由於優先級的問題,她就不會去訪問你的prototype了,直接給你覆蓋掉了

比較了四種變量後直到prototype有什麼好處了嗎,這下次也可以理解爲什麼函數都會有prototype了嗎,如果不理解的話多看幾遍啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章