Javascript中的繼承與Prototype

來源:互聯網
上載者:User

標籤:

    之前學習js僅僅是把w3school上的基本文法看了一次而已,再後來細看書的時候,書中會出現很多很多沒有聽過的文法,其中一個就是js的繼承以及總能看到的prototype。我主要在看的兩本js書是《javascript權威指南》,也就是那本犀牛書,還有一本是瘋狂xx系列的《瘋HTML5/CSS3/Javascript講義》。前者非常適合用啃js細節,如果需要深入學習一些js內部機制以及相關的內容,這本大塊頭啃起來還是挺有味道的。後者是本速成教材,可以讓你對某個概念有一個非常舒服的開啟檔案,不晦澀,淺顯易懂。大家如果看完w3school之後,感覺沒有學到什麼東西的話,應該試著去看看書,這是我剛開始學習前端總結出來的小建議。

     先說說繼承,在js裡面其實是沒有繼承的概念。但大家應該都知道,在物件導向的程式設計裡,類之間有顯示的繼承關係,一個類可以顯示地指定繼承自哪一個類,然後繼承下來的子類就會有父類的屬性和方法。js裡沒有這一概念,但是它一種類似繼承的方法來對原來的類進行擴充。這種方式就是通過類的prototype屬性,來為類動態增加屬性和方法,這種方式類似於繼承,但它只能稱作是“偽繼承”,因為這種繼承的實質是修改了原有的類,而不是產生一個子類。

     我們先說不用繼承的時候,js通過什麼樣的方法來為對象增加屬性和方法呢。

     首先,程式為一個對象的並不存在屬性進行賦值的時候,就可以認為是為這個對象增加了屬性。

【代碼01】

                              var obj = {};                              obj.name = "Jeremy";                              obj.info = function(){                                  console.log("This is a method");                              }

    在這裡插入說明一下函數、方法、對象還有類的概念理解。

   函數,在javascript裡面有“一等公民”之稱,當在js中定義了一個函數之後,其實就是產生了以下:

   1)函數:類似於java的方法,它可以被調用;

   2)對象:當定義了一個函數時候,系統也就建立了一個對象,這個對象是Function類的執行個體;

   3)方法:定義了一個函數的時候,這個函數會被附加給某個對象,作為某個對象的方法:

【代碼02】

                              function Person(name,gender){var val = "valueName";//局部變數this.name = name;this.gender = gender;//定義了一個匿名函數。相當於為Person對象指定了info方法this.info = function(){console.log("name:"+this.name);console.log("gender:"+this.gender);console.log("val:"+val);}}var p1 = new Person(‘Jeremy‘,‘male‘);//執行個體p1去調用方法info()var v = p1.info();console.log("這裡能訪問到局部變數val:"+v);
 
 
 
4)類:在定義函數的同時,即得到一個和函數同名的類,而這個函數就是該類的構造器,所以在定義一個函數的時候,實際

就是定義了一個構造器

 

我們來看上面的代碼02。

    程式定義了一個函數Person,同時也就定義了Person類,函數即類的構造器,這個函數為Person執行個體p1提供了info方法。

雖然這樣我們也完成了對Person的方法增加,但是這樣做會存在一些問題。例如效能會低下,每次建立Person對象的時候就會有很多info函數,這樣會造成系統記憶體流失(實際是什麼情況我暫時沒有去探究了),引起效能下降。還有一個很明顯的問題,知道js閉包的朋友應該發現了,在info()函數裡訪問局部變數val,形成了閉包(這裡不對閉包展開說了)。然而這會導致val變數的範圍擴大,在代碼末尾,程式依舊可以訪問到局部變數值。

 

   所以!為了避免這些不好的事情的發生!建議使用prototype屬性。

   首先在javascript中,每一個javascript對象(null除外)都會和另外一個對象相關聯,這個另一個對象就是原型,js中的每一個對象都是從原型那裡繼承屬性。在建立對象的3種方法裡面,通過對象直接量建立的對象都具有同一個對象原型,可以通過Object.prototype獲得對對象原型的引用。通過關鍵字new建構函式建立的對象的原型即使建構函式的prototype的值。所以,和使用var empty={};建立對象一樣,通過new Object()建立的對象也繼承自Object.prototype。

【對象直接量建立對象】即由若干的名/值對組成的映射表。就像這樣:

var empty={};//屬性為空白的對象var person={name:"gua",age:"18"};//具有name和age屬性的值
【new關鍵字建立對象】通過new關鍵字建立並初始化一個新的對象。形式上就是new後面跟一個函數調用,這裡的函數稱作建構函式(constructor),這個
建構函式用於初始化一個新建立的對象。就像這樣:
var obj = new Object();var arr = new Array();
 
 換個好理解一些的說法,就是js對象都是有相同基類(object)的執行個體。
 
 嗯,我也覺得這一段比較晦澀。
 那來看一下代碼是怎麼實現的就好了。
 function Person(name,gender){this.name = name;this.gender = gender;//定義了一個匿名函數。相當於為Person對象指定了info方法this.info = function(){console.log("name:"+this.name);console.log("gender:"+this.gender);}}var p1 = new Person(‘Jeremy‘,‘male‘);p1.info();//為Person類的prototype屬性增加了walk函數,即可以認為為Person類動態增加walk執行個體方法Person.prototype.walk = function(){console.log(this.name +" 正在散步.......一步一步.....");}var p2 = new Person(‘Guagua‘,‘female‘);p2.info();//執行p2的walk方法p2.walk();        //js已經為類Person動態增加了方法walk,所以p1也具有了walk方法。p1.walk();
                

運行結果:

 

這段程式採用prototype為Person類增加了一個walk方法,這讓所有的Person執行個體共用了一個walk方法,而walk方法並不在Person函數之內,所以就不會產生閉包。

 

所以我們應該避免使用內嵌函數為類定義方法,使用增加prototype屬性的方式來增加方法。

 

以上是我最近看書學習整理出來的一些內容,有不對的地方望大家指正。

Javascript中的繼承與Prototype

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.