交叉着寫Java和Javascript都有2年多了,今天來總結下本身所瞭解的Javascript類與繼承。javascript
Javascript自己沒有相似Java的面向對象的類與繼承術語,但其基於原型對象的思想卻能夠輕鬆實現各類類和繼承。java
下面來描述實現類的第一種方法,請看例子:chrome
function People(name, age){ this.name = name; this.age = age; this.say = function(){ console.log('hello, javascript!'); }; }
var people = new People('sky',25);
people.say();
從形式上看上去,與面向對象的類幾乎同樣,this爲實例化後的對象自身,name/age爲成員變量,say爲成員方法,但其內部原理卻相差甚遠。函數
接下來分析其中的不一樣之處,先看一下代碼:this
var people_1 = new People('sky1',21); var people_2 = new People('sky2',22);
people_1.say == people_2.say//false
按照面向對象語言的特徵,表面上看上去people_1/2都有本身的屬性name/age,有公共的(佔用同一分內存區域)方法say,但在JS中並不是如此。spa
首先,People自身是一個對象,new People產生了兩個對象people_1/2,每一個對象都擁有各自的內存空間,即將name/age/say在各自空間都存在一份。prototype
可經過 people_1.say == people_2.say 驗證,結合下圖可清楚得出結論,每一個對象之間是獨立的個體,沒有關聯關係。code
接下來,結合JS原型概念構造類的第二種方法。原型是JS的核心概念,後續篇章詳細描述。對象
function People(name,age){ this.name=name; this.age=age; } People.prototype.say = function(){ console.log('hello, javascript!'); }; var people_1 = new People('sky1',21); var people_2 = new People('sky2',22); people_1.say == people_2.say//true
經過看到上述代碼結果,可得出people_1/2共享成員say,可經過下圖分析。這裏涉及到了原型鏈的概念,後面和原型一塊兒闡明。blog
關於類的構造就介紹到這。接下來描述實現繼承的幾種方法。
先來看第一種,基於類式繼承的方式。
function People(name,age,sex){ this.name=name; this.age=age; this.sex=sex; this.say=function(){ console.log('hello,javascript!'); }; } function Man(name,age){ People.call(this,name,age,'male'); } function Woman(name,age){ People.call(this,name,age,'female'); }
var man = new Man('sky-man',21);
var woman = new Woman('sky-woman',22);
man.say();
woman.say();
這種繼承基於第一種類的構造形式,即採用複製的方法實現子類對象對父類成員的繼承。
其中,起復製做用的關鍵在與People.call(this,...)語句上,意思是使用call方法借用People函數來構造Man對象。
這裏不太好理解,首先要理解call方法如何使用,其次要了解this做用域的概念和使用。關於做用域及做用域鏈概念也在之後的篇章中闡述。
總之,這裏的意義是將People對象的屬性複製到Man對象上。
咱們看下這裏的圖形描述:
很顯然man/woman都繼承了People的成員變量,但其採用的是複製的方法,對象之間並無創建真正的繼承。
接下來將基於第二種構造類的方法來介紹第二種構造類的形式,即繼承依賴原型。直接看一下代碼:
function People(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } People.prototype.say=function(){ console.log('hello,javascript!'); } function Man(name,age){ People.call(this,name,age,'male'); } Man.prototype = Object.create(People.prototype); function Woman(name,age){ People.call(this,name,age,'female'); } Woman.prototype = Object.create(People.prototype);
上面的代碼可能已經引入一些JS原理層面的東西,仍是先用圖來展現:
上圖中引入幾個比較JS原理的東西,prototype/constructor/__proto__,其中前二者是JS標準中存在的,
而__proto__是標準中未暴露的,該名稱採用chrome暴露的屬性名。
其中prototype是原型函數,每一個函數中都存在;constructor是構造器,每一個對象都存在;__proto__是原型對象,每一個對象都存在。
此處先介紹到這,後期將根據ECMAScript標準詳細介紹幾者之間的關係。
經過上面的線條能夠了解每一個對象之間的關係,以及原型鏈在其中所起的做用。
能夠看出,第二種繼承方法是基於原型的,雖然成員是採用複製的方式,但保證了方法的繼承性。這與傳統面向對象類繼承意義上纔是一致的。
經過上面的類的構造和繼承方式,咱們對Javascript原型繼承有必定了解。那麼若是要實現內部成員,內部方法,該如何實現呢?
疑問將在下個篇章解答。