### 一,面相對象繼承機制
今天算是什么都沒干,盡在了解面向對象三大特性之一的繼承了,過去的學習的C++和C#都是正統的面向對象語言,學習的時候也沒有怎么深入了解過,只是簡單的學習最基礎的繼承。下午在看繼承機制的時候,看到一個很經典的繼承機制實例。這個實例使用UML很好的解釋了繼承機制。
說明繼承機制最簡單的方式是,利用一個經典的例子就是幾何形狀。實際上,幾何形狀只有兩種,即橢圓形(是圓形的)和多邊形(具有一定數量的邊)。圓是橢圓的一種,它只有一個焦點。三角形、矩形和五邊形都是多邊形的一種,具有不同數量的邊。正方形是矩形的一種,所有的邊等長。這就構成了一種完美的繼承關系,很好的解釋了面向對象的繼承機制。
在這個例子中,形狀是橢圓形和多邊形的基類(通常我們也可以叫它父類,所有類都由它繼承而來)。橢圓具有一個屬性(foci),說明橢圓具有的焦點的個數。圓形繼承了橢圓形,因此圓形是橢圓形的子類,橢圓形是圓形的超類。同樣,三角形、矩形和五邊形都是多邊形的子類,多邊形是它們的超類。最后,正方形繼承了矩形。
最好用圖來解釋這種繼承關系,這是 UML(統一建模語言)的用武之地。UML的主要用途之一是,可視化地表示像繼承這樣的復雜對象關系。下面的圖示是解釋形狀和它的子類之間關系的UML圖示:

在UML中,每個方框表示一個類,由類名說明。三角形 、矩形和五邊形頂部的線段匯集在一起,指向形狀,說明這些類都由形狀繼承而來。同樣,從正方形指向矩形的箭頭說明了它們之間的繼承關系。
### 二,ECMAScript繼承機制的實現
要用ECMAScript實現繼承機制,您可以從要繼承的基類入手。所有開發者定義的類都可作為基類。出于安全原因,本地類和宿主類不能作為基類,這樣可以防止公用訪問編譯過的瀏覽器級的代碼,因為這些代碼可以被用于惡意攻擊。
選定基類后,就可以創建它的子類了。是否使用基類完全由你決定。有時,你可能想創建一個不能直接使用的基類,它只是用于給子類提供通用的函數。在這種情況下,基類被看作抽象類。盡管ECMAScript并沒有像其他語言那樣嚴格地定義抽象類,但有時它的確會創建一些不允許使用的類。通常,我們稱這種類為抽象類。
創建的子類將繼承超類的所有屬性和方法,包括構造函數及方法的實現。記住,所有屬性和方法都是公用的,因此子類可直接訪問這些方法。子類還可添加超類中沒有的新屬性和方法,也可以覆蓋超類的屬性和方法。由于JS并不是正統的面向對象語言,一些名詞也需要做出改變。
### 三,ECMAScript繼承的方式
ECMAScript語言中將被繼承的類(基類)稱為超類型,子類(或派生類)稱為子類型。和其他功能一樣,ECMAScript實現繼承的方式不止一種。這是因為JavaScript中的繼承機制并不是明確規定的,而是通過模仿實現的。這意味著所有的繼承細節并非完全由解釋程序處理。作為開發者,你有權決定最適用的繼承方式。下面為您介紹幾種具體的繼承方式。
(1)原型鏈方式
繼承這種形式在ECMAScript中原本是用于原型鏈的。上一篇博文已經介紹了創建對象的原型方式。原型鏈擴展了這種方式,以一種有趣的方式實現繼承機制。prototype對象是個模板,要實例化的對象都以這個模板為基礎。總而言之,prototype 對象的任何屬性和方法都被傳遞給那個類的所有實例。原型鏈利用這種功能來實現繼承機制。我們來看一個例子:
~~~
function A() {//超類型A中必須沒有參數
this.color = "red";
this.showColor = function () {
return this.color;
};
};
function B() {//子類型B
this.name = "John";
this.showName = function () {
return this.name;
};
};
B.prototype = new A();//子類型B繼承了超類型A,通過原型,形成鏈條
var a = new A();
var b = new B();
document.write(a.showColor());//輸出:blue
document.write(b.showColor());//輸出:red
document.write(b.showName());//輸出:John
~~~
在原型鏈中,instanceof運算符的運行方式也很獨特。對B的所有實例,instanceof為A和B都返回true。
ECMAScript的弱類型世界中,這是極其有用的工具,不過使用對象冒充時不能使用它。例如:
~~~
var b = new B();
document.write(b instanceof A);//輸出:true
document.write(b instanceof B);//輸出:true
~~~
使用原型鏈方式實現了繼承,但是這種方式無法共享和子類型給超類型傳遞參數。我們可以借用構造函數方式(也
就是對像冒充)的方式來解決這兩個問題。
(2)對象冒充方式
對象冒充方式的其原理如下:構造函數使用this關鍵字給所有屬性和方法賦值(即采用對象聲明的構造函數方式)。因為構造函數只是一個函數,所以可使A構造函數成為B的方法,然后調用它。B就會收到A的構造函數中定義的屬性和方法。例如,用下面的方式改寫上面的例子創建對象A和B:
1call()方法
~~~
function A(Color) {//創建超類型A
this.color = Color;
this.showColor = function () {
return this.color;
};
};
function B(Color,Name) {//創建子類型B
A.call(this, Color);//對象冒充,給超類型傳參
this.name = Name;//新添加的屬性
this.showName =
};
var a = new A("blue");
var b = new B("red", "John");
document.write(a.showColor());//輸出:blue
document.write(b.showColor());//輸出:red
document.write(b.showName());//輸出:John
~~~
? ? ?2apply()方法
? ? 和上面call()方法唯一的區別就是在子類型B中的代碼:
~~~
A.call(this,arguments);//對象冒充,給超類型傳參
~~~
當然,只有超類型中的參數順序與子類型中的參數順序完全一致時才可以傳遞參數對象。如果不是,就必須創建一個單獨的數組,按照正確的順序放置參數。
使用對象冒充方式雖然解決了共享和傳參的問題,但是沒有原型,復用就更不可能了,所以我們組合上述的兩種方式,即原型鏈方式和對象冒充的方式實現JS的繼承。
(3)混合方式
這種繼承方式使用構造函數定義類,并非使用任何原型。對象冒充的主要問題是必須使用構造函數方式,這不是最好的選擇。不過如果使用原型鏈,就無法使用帶參數的構造函數了。開發者如何選擇呢?答案很簡單,兩者都用。
由于這種混合方式使用了原型鏈,所以instanceof運算符仍能正確運行。
在上一篇博文,創建對象的最好方式是用構造函數定義屬性,用原型定義方法。這種方式同樣適用于繼承機制,用對象冒充繼承構造函數的屬性,用原型鏈繼承prototype對象的方法。用這兩種方式重寫前面的例子,代碼如下:
~~~
function A(Color) {
this.color = Color;
};
A.prototype.showColor = function () {
return this.color;
};
function B(Color, Name) {
A.call(this, Color);//對象冒充
this.name = Name;
};
B.prototype = new A();//使用原型鏈繼承
B.prototype.showName = function () {
return this.name;
};
var a = new A("blue");
var b = new B("red", "John");
document.write(a.showColor());//輸出:blue
document.write(b.showColor());//輸出:red
document.write(b.showName());//輸出:John
~~~
繼承的方式和創建對象的方式有一定的聯系,推薦使用的繼承方式還時原型鏈和對象冒充的混合方式。使用這種
混合方式可以避免一些不必要的問題。
看這篇博文的時候,必須看一下前面的創建對象的方式:[輕松學習JavaScript十二:JavaScript基于面向對象之創](http://blog.csdn.net/erlian1992/article/details/50211229)[建對象(一)](http://blog.csdn.net/erlian1992/article/details/50211229)和[輕松學習JavaScript十二:JavaScript基于面向對象之創建對象(二)](http://blog.csdn.net/erlian1992/article/details/50224073)。那么理解起來應該沒有那么難了,
JS面向對象的一些概念時需要我們回過頭來再理解的。
- 前言
- HTML學習1:Dreamweaver8的安裝
- HTML學習2:初識HTML
- HTML學習3:常用標簽之文本標簽
- HTML學習4:常用標簽之列表標簽
- HTML學習5:常用標簽之圖像標簽
- HTML學習6:常用標簽之超鏈接標簽
- HTML學習7:常用標簽之表格標簽
- HTML學習8:常用標簽之框架標簽
- HTML學習9:常用標簽之表單標簽
- HTML學習10:表單格式化
- HTML學習11:HTTP 方法
- HTML學習12:其他常見標簽之頭標簽
- HTML學習13:其他常見標簽之體標簽
- 輕松學習JavaScript一:為什么學習JavaScript
- 輕松學習JavaScript二:JavaScript語言的基本語法要求
- 輕松學習JavaScript三:JavaScript與HTML的結合
- 輕松學習JavaScript四:JS點擊燈泡來點亮或熄滅這盞燈的網頁特效映射出JS在HTML中作用
- 輕松學習JavaScript五:JavaScript的變量和數據類型
- 輕松學習JavaScript六:JavaScript的表達式與運算符
- 輕松學習JavaScript七:JavaScript的流程控制語句
- 輕松學習JavaScript八:JavaScript函數
- 輕松學習JavaScript九:JavaScript對象和數組
- 輕松學習JavaScript十:JavaScript的Date對象制作一個簡易鐘表
- 輕松學習JavaScript十一:JavaScript基本類型(包含類型轉換)和引用類型
- 輕松學習JavaScript十二:JavaScript基于面向對象之創建對象(一)
- 輕松學習JavaScript十二:JavaScript基于面向對象之創建對象(二)
- 輕松學習JavaScript十三:JavaScript基于面向對象之繼承(包含面向對象繼承機制)
- 輕松學習JavaScript十四:JavaScript的RegExp對象(正則表達式)
- 輕松學習JavaScript十五:JavaScript之BOM簡介
- 輕松學習JavaScript十六:JavaScript的BOM學習(一)
- 輕松學習JavaScript十七:JavaScript的BOM學習(二)
- 輕松學習JavaScript二十九:JavaScript中的this詳解
- CSS基礎學習一:CSS概述
- CSS基礎學習二:如何創建 CSS
- CSS基礎學習三:CSS語法
- CSS基礎學習四:元素選擇器
- CSS基礎學習五:類選擇器
- CSS基礎學習六:id選擇器
- CSS基礎學習七:屬性選擇器
- CSS基礎學習八:派生選擇器
- CSS基礎學習九:偽類
- CSS基礎學習十:偽元素
- CSS基礎學習十一:選擇器的優先級
- CSS基礎學習十二:CSS樣式
- CSS基礎學習十三:盒子模型
- CSS基礎學習十四:盒子模型補充之display屬性設置
- CSS基礎學習十五:盒子模型補充之外邊距合并
- CSS基礎學習十六:CSS盒子模型補充之border-radius屬性
- CSS基礎學習十七:CSS布局之定位
- CSS基礎學習十八:CSS布局之浮動
- CSS基礎學習十九:CSS布局之圖文混排,圖像簽名,多圖拼接和圖片特效
- DIV+CSS實操一:經管系網頁總體模塊布局
- DIV+CSS實操二:經管系網頁添加導航欄和友情鏈接欄
- DIV+CSS實操三:經管系網頁內容模塊添加標題欄和版權信息模塊
- DIV+CSS實操四:經管系網頁內容模塊內容添加(一)
- DIV+CSS實操五:經管系網頁內容模塊內容添加(二)
- DIV+CSS實操六:經管系網頁添加導航欄下拉菜單
- DIV+CSS實操七:中文系內容模塊控制文本不換行和超出指定寬度后用省略號代替
- JS中實現字符串和數組的相互轉化