摘要:構造函數實例和原型的概念和關系每個函數都屬于對象,都會有一個屬性叫。這也是繼承的依據。這樣一來,原型找不到構造函數,這是非常蛋疼的事情,違反了原型鏈的定義啊。所以現在子對象原型和父對象原型是就建立關系了。
構造函數、實例和原型的概念和關系
每個函數都屬于對象,都會有一個屬性叫prototype。這個屬性指向一個對象,我們把他叫做當前函數的原型對象。原型對象下面有個屬性叫constructor.這個屬性指向當前函數。函數又分為普通函數和構造函數。這里我們說一下構造函數。
定義一個函數 :
function Person(x, y ) { this.age = x; this.name = y; } var xiaoming= new Person(12, "xiaoming" );
這里創建實例對象 xiaoming的時候就是調用了Person構造函數,使xiaoming有了自己的屬性和方法,之后xiaoming和Person也就沒有什么直接交集了(可以理解為小明分手了,哎程序員好難╥..╥)
但是每個實例對象都會有一個隱藏屬性[[prototype]],這個屬性在chrome/firefox下叫__proto__,僅僅供學習調試用.它指向的就是構造函數的原型對象。
對于這個原型對象,我們就要重點理解下了。這個對象的作用就是為了讓所有的實例對象都能共享這個對象的屬性和方法(當然實例本身的屬性和方法優先級是高于原型的)。每個構造函數都會有一個默認的原型對象。我們只要在改原型對象上做文章就可以實現很多功能。
● 共享屬性和方法:
Person.prototype.eyes = 2; Person.prototype.walk = function ( ){……}; var xiaoming= new Person(12, "xiaoming" ); var xiaohong= new Person(12, "xiaohong" ); xiaoming.eyes xiaohong.eyes // 小明和小紅都有2只眼 xiaoming.walk xiaohong.walk //小明和小紅都會走路
● 原型鏈:
我們先做一個假設,假如我們把一個函數對象Man的原型直接給換成另一個函數對象Person的實例對象xiaoming會怎么樣呢?
前面說了,通過實例對象是可以找到函數對象Person的原型。那我們現在Man對象的實例xiaoming是不是也就可以訪問到Person對象的原型對象了呢。
function Man( ) { this.beard = "xxx"; } Man.prototype = new Person( 23, "xiaoming" ); 這里我們相當于把默認的那個原型給重寫了,給參數其實就是給原型添加屬性和方法 var xiaoming = new Man(); xiaoming.beard //xxx 這里實例xiaoming自己的屬性(小明有胡子) xiaoming.age //23 xiaoming.name //xiaoming 這兩個屬性是實例的原型上面的屬性(其實這個屬性是Person實例的屬性,但是現在的原型不就是Person實例嗎) xiaoming.eyes //2 這個屬性呢,是Person的原型對象上面的了
這里我們基本上都可以訪問到,是不是有點繼承的味道了。
如果我們再這樣搞一個對象,也這么干,這里是不是就感覺像條鏈一樣。最頂端的對象是Object,也就是說到最后了。我們把這條鏈接方式叫做原型鏈。這也是繼承的依據。
和傳統的OOP語言來說,JavaScript語言比較蛋疼的是它沒有類這個機制。所以說我們事先js的繼承就從對象角度下手了。我們重點說一下依據原型鏈繼承的。(其他的繼承我就不說了,比如借用父對象的構造函數等,實用性不強)
1.上面所說的實現原型鏈的方法雖然有點繼承的味道了,但是你有沒有發現 實例化xiaoming這個對象的時候調用了Man這個構造函數,但是xiaoming自己的age和name都沒能進行構造,只不過是原型上的屬性而已(其實是Person自己構造的,new Person( 23, "xiaoming" ))。我們其實可以這樣用call和apply這個object原型下面給我們定義好的方法改進下(call和apply方法自己看api說明吧)
function Man(x, y) { Person.call(this, x, y); //這里你可以這樣理解,this指的是Man,這樣其實就是借用Person構造函數 this.beard = "xxx"; }
我們把Man的構造函數這樣一改,實例化的時候傳參,這樣age和name這兩個屬性就是Man自己構造出來的了,并不會被共享
Man.prototype = new Person( ); Man.prototype.constructor = Man; var xiaoming = new Man(23, "xiaoming");
這里只是讓Man的原型的構造函數變成原有的構造函數,如果不加這一句的話,那么Man原型的構造函數就變成undefied,因為實例和構造函數并沒有直接關系。這樣一來,原型找不到構造函數,這是非常蛋疼的事情,違反了原型鏈的定義啊。
這邊可能會有人問了,我為什么不自己像胡子beard 那個屬性一樣直接構造呢。
大哥,我這是舉例子,你以為實際的項目中就會有這么兩個屬性嗎。而且這樣不正是繼承的目的嗎
可以少寫很多代碼啊。(說多了都是淚)
但是也是有缺點的:兩次調用父類構造函數(第一次是在創建子類原型的時候,第二次是在子類構造函數內部);子類繼承父類的屬性,一組在子類實例上,一組在子類原型上(在子類原型上創建不必要的多余的屬性,實例上的屏蔽原型上的同名屬性,是不是感覺有點多余了 ,效率低。
2.為了改進這種方法,下面說的這種繼承方式是借助我們偉大的道爺(這個人很厲害,自行百度)的靈感 。這種就是利用一個空函數對象來做一個橋梁.
具體實現方式如下:
function inherits(Child, Parent) { var F = function () {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; }
另外在子對象的構造函數中別忘了借用父對象的構造函數哦。(就是那個call或者apply方法)
這里和上面的區別是,子對象的原型現在不是父對象的實例了,變成了空函數對象的實例(父對象不用再創建兩次了,并且子對象的原型上也不會有啥屬性和方法了)。而空函數對象的原型變成了父對象的原型。前面我們說過,有了實例就能找到原型。所以現在子對象原型和父對象原型是就建立關系了。這種方式現在是最穩的方法,也已經被很多框架給寫到源碼里面了。
這里我們就用google closure 關于繼承的兩個api,這邊簡單舉個例子:
Child = function( ){ goog.base(this); this.height = 12; } goog.inherits(Child, Parent);
這里就實現了我們上述實現的,不過封裝起來了而已。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91355.html
摘要:之前有朋友問怎么去理解原型和原型鏈的問題。理解原型鏈的小技巧將箭頭視作泛化子類到父類關系那么圖中所有的虛線將構成一個繼承層級,而實線表示屬性引用。原型鏈是實現繼承的重要方式,原型鏈的形成是真正是靠而非。 之前有朋友問怎么去理解原型和原型鏈的問題。這個問題,在面試中,很多同學經常都會遇到。這里給大家講講,方便大家記憶。 JavaScript的特點JavaScript是一門直譯式腳本...
摘要:之前有朋友問怎么去理解原型和原型鏈的問題。理解原型鏈的小技巧將箭頭視作泛化子類到父類關系那么圖中所有的虛線將構成一個繼承層級,而實線表示屬性引用。原型鏈是實現繼承的重要方式,原型鏈的形成是真正是靠而非。 之前有朋友問怎么去理解原型和原型鏈的問題。這個問題,在面試中,很多同學經常都會遇到。這里給大家講講,方便大家記憶。 JavaScript的特點JavaScript是一門直譯式腳本...
摘要:相當于在用原型繼承編寫復雜代碼前理解原型繼承模型十分重要。同時,還要清楚代碼中原型鏈的長度,并在必要時結束原型鏈,以避免可能存在的性能問題。 js是一門動態語言,js沒有類的概念,ES6 新增了class 關鍵字,但只是語法糖,JavaScript 仍舊是基于原型。 至于繼承,js的繼承與java這種傳統的繼承不一樣.js是基于原型鏈的繼承. 在javascript里面,每個對象都有一...
摘要:在節中,我們學習到了通過構造函數創建對象的三個重要步驟,其中的一步是把構造函數的對象設置為創建對象的原型。利用而不是直接用創建一個實例對象的目的是,減少一次調用父構造函數的執行。 JavaScript語言不像面向對象的編程語言中有類的概念,所以也就沒有類之間直接的繼承,JavaScript中只有對象,使用函數模擬類,基于對象之間的原型鏈來實現繼承關系,ES6的語法中新增了class關鍵...
摘要:原型對象是由創建的,因此原型對象的構造函數是構造函數也可以是稱為對象,原型對象也就繼承了其生父構造函數中的數據,也同時繼承了原型對象的數據。當然這條原型鏈中的數據,會被還是還是這類構造函數繼承,但是不會被這些繼承,他們不處于同一個鏈條上。 js中,Function的本質是什么?Object的本質又是什么?js中有幾條原型鏈? showImg(https://segmentfault.c...
閱讀 909·2021-09-09 09:32
閱讀 2849·2021-09-02 10:20
閱讀 2685·2021-07-23 11:24
閱讀 824·2019-08-30 15:54
閱讀 3631·2019-08-30 15:54
閱讀 1346·2019-08-30 11:02
閱讀 2844·2019-08-26 17:40
閱讀 1122·2019-08-26 13:55