js繼承的方法 如何理解JavaScript的原型和原型鏈?
如何理解JavaScript的原型和原型鏈?JavaScript中的原型和原型鏈都是實現OOP的手段。OOP在JavaScript中的具體實現如下:對象是屬性的集合。特別地,其值是函數的屬性是方法。相
如何理解JavaScript的原型和原型鏈?
JavaScript中的原型和原型鏈都是實現OOP的手段。OOP在JavaScript中的具體實現如下:
對象是屬性的集合。特別地,其值是函數的屬性是方法。相似對象的公共屬性被提取并聚集在一起形成一個類。這些對象被稱為這個類的實例。同樣,相似類的公共屬性被提取出來,聚集在一起形成一個新類,這個新類是以前類的超類,以前的類是這個類的子類。。多個超類也可以作為子類來聚集一個新的超類,這個過程會一直持續下去,直到出現一個名為Object的類,并且它的超類為Null。
類不僅是公共屬性的集合,還是對象工廠。類的實例對象是由該類的構造函數創建的。構造函數負責兩件事:
創建一個對象;
初始化對象;
因為方法已經提供了前者的實現,所以構造函數真正需要做的是初始化對象,這分為兩件事:
讓對象具有由類收集的公共屬性;
根據參數,一些對象的屬性被特殊化;
對于第二件事,沒什么好說的,就是給要初始化的對象添加專門的屬性。對于第一件事,你也可以模仿后一種實現方法,但這并不是一個明智的選擇,因為這些公共屬性的值在大多數情況下是不會改變的。賈瓦斯選擇抄本腳本的方法:
將這些公共屬性作為屬性,并賦予它們默認的屬性值,創建一個原型對象;
初始化時,原型對象被賦予要初始化的對象的特殊屬性:_ _ proto _ _
也就是說,一個類對應一個原型對象,初始化時用_ _ proto _ _連接實例對象和原型對象。
特殊屬性__proto__不僅負責連接實例和原型,還負責連接子類和超類的原型對象,實現類之間的繼承關系。這樣,一個對象的類原型、超類原型、超類原型就通過__proto__連接起來了。變成一個 "鏈條 ",稱為對象的原型鏈。是的,一個對象的__proto__屬性為null,說明這個對象沒有原型鏈,Object類的原型是這樣的。
為了實現通過原型初始化實例的方法,需要在訪問對象的屬性時相互協作:
讀取屬性值:先在對象中尋找屬性,如果存在則返回其值;否則,在prototype對象中查找,如果存在則返回其值;否則在prototype對象的prototype對象中查找,直到原型鏈為空,表示該屬性未定義,返回undefi。Ned;
給屬性賦值:找到對象中的屬性,如果存在就給它賦值,如果不存在就在對象中創建屬性并給它賦值;
刪除屬性:如果屬性存在于對象中,刪除它,否則不做任何事情。
這種訪問機制保證了對象屬性可以覆蓋(揭開)原型屬性,但不會改變原型屬性,這就是OOP的多態性。
構造函數在創建對象時需要使用prototype對象,通過prototype屬性知道其對應類的prototype對象。此外,為了讓實例對象知道誰創建了它,它的構造函數屬性 "抓取 "構造函數。原型類對圖像也被認為是由這個類的構造函數創建的。
接下來,讓我們 讓我們看看實現OOP的具體代碼:
首先,不考慮繼承關系,聲明類的示例代碼如下:
注意:應該避免直接使用特殊屬性__proto__。正式的是調用方法,方法的參數是要創建的對象的原型對象。注意:按照OOP語言的傳統,構造函數的名字就是類的名字。
當一個函數被調用時,如果這個上下文被綁定到一個普通的對象(而不是空的或者全局的對象窗口),這個函數被作為對象的方法調用。
當我們用一個新的表達式創建一個對象時,構造函數被new以方法的形式調用:
在上面的示例代碼中,構造函數在開頭和結尾所做的事情,新的表達式,為我們做了:
New會創建一個空白對象,使其原型鏈綁定構造函數的原型屬性,使其構造函數屬性綁定構造函數;然后調用構造函數,將此對象作為此的上下文,如果構造函數如果函數不返回值,則使用一個空白對象作為創建的對象。用代碼寫的是:
new調用的構造函數已經轉化為構造函數,但為了保持其構造函數能力,一般實現如下:
接下來,考慮類的繼承。
實例對象的初始化過程是:先被超類的構造函數初始化,再被子類的構造函數初始化,以滿足子類覆蓋超類的要求。基于此,示例代碼如下:
寫到這里,我們發現是一堆標準代碼不得不寫。所以早期很多前端框架陸續提供了上述代碼的封裝方案,但是一直沒有統一的解決方案,直到ES6直接提供了類語法,整個事情才告一段落:
注意:JavaScript中的屬性分為存儲屬性和訪問屬性(分別對應傳統OOP語言中的字段和屬性)。只有原型中的方法和訪問屬性可以在類中聲明,而存儲是在原型中聲明的。屬性必須是老方法。
類表達只是語法層面的封裝,最終還是基于原型和原型鏈。
雖然我們不。;現在不需要根據那套復雜的規范來聲明類,理解原型和原型鏈,深入理解JavaScript的OOP機制仍然非常重要。
最后給出JavaScript內置對象之間的原型鏈圖(粗箭頭為__proto__屬性,細箭頭為原型屬性,虛箭頭為構造器屬性):
(Value: number, string, Boolean; Symbol, container : array, set, map)
ES6和以前的javascript的區別?
ES6是js的新標準,ES6之前的標準本質上都是原型繼承函數p(){ this . x 5 } functions(){ this . y 6。