JavaScript 是一個強大的物件導向程式語言,但是,並不像傳統的程式語言,它採用一個以原型為基礎的OOP模型,致使它的語法讓大多數開發人員看不懂。另外,JavaScript 也把函數當作首要的對象,這可能會對不夠熟悉這門語言的開發人員造成更大的困惑。那就是我們決定放在前面作為一個簡短前言進行介紹的原因,並且在 JavaScript 裡也可以用作物件導向程式設計的一個參考。
這個文件沒有提供一個物件導向程式設計的規則預覽,但有它們的介面概述。
隨著越來越多的第三方函式庫,框架和web依賴的出現,JavaScript發展中的命名空間是勢在必行的,我們得盡量避免在全域命名空間的物件和變數的衝突。
不幸的是,JavaScript並沒有提供支援命名空間的編譯,但我們可以使用物件來得到相同結果。在JavaScript中我們有許多種模式來實現命名空間接口,但是我們覆蓋嵌套的命名空間,它在該領域是最常用的模式。
嵌套的命名空間模式使用物件字面量來捆綁一個特定應用的特定名字的功能。
我們最初創建一個全域對象,並且賦值給一個稱為MyApp的變數。
上述的語法會檢查MyApp是否已經被定義過。假如它已經被定義過,我們簡單地把它賦值給自己,但是,我們創建一個空的容器來裝載我們的函數和變數。
我們也可以使用相同技術來建立子命名空間。例如:
我們一旦啟動我們的容器,我們可以在(容器)內部定義我們的函數和變量,並且在全域命名空間中呼叫它們,不需要冒著與現有定義衝突的風險。
在JavaScript命名模式的一個內部概述是由Goggle的Addy Osmani在Essential JavaScript Namespacing Patterns的文章中介紹的。假如你想探索不同的模式,這裡將會是個美好的起點。
如果你寫過 JavaScript 程式碼,那你已經使用過物件了。 JavaScript 有三種類型的物件:
原生物件是語言規範的一部分,不管在什麼樣的運行環境下運行,原生物件都可用。原生物件包括:Array、Date、Math 和 parseInt 等。若想了解所有原生對象,請參閱 JavaScript 內建物件參考
與原生物件不同,宿主物件是由JavaScript 程式碼執行的環境創建。不同的環境環境創建有不同的宿主物件。這些宿主物件在多數情況下都允許我們與之互動。如果我們寫的是在瀏覽器(這是其中一個運行環境)上運行的程式碼,會有 window、document、location 和 history 等宿主物件。
使用者物件(或植入物件)是在我們的程式碼中定義的對象,在執行的過程中建立。 JavaScript 中有兩種方式可以創造自己的對象,以下詳述。
在前面示範創建命名空間的時候,我們已經接觸到了物件字面量。現在來搞清楚物件字面量的定義:物件字面量是置於一對花括號中的,由逗號分隔的名-值對清單。物件字面量可擁有變數(屬性)和函數(方法)。像 JavaScript 中的其它物件一樣,它也可以作為函數的參數,或傳回值。
現在定義一個物件字面量並賦予一個變數:
向這個物件字面量新增屬性和方法,然後在全域作用域存取:
這看起來和前面的命名空間很像,但這並不是巧合。字面量物件最典型的用法就是把程式碼封裝起來,使其在一個封裝的套件中,以避免與全域作用域中的變數或物件發生衝突。由於類似的原因,它也常用於向插件或物件傳遞配置參數。
如果你熟悉設計模式的話,物件字面量在某種程度上來說就是單例,就是那種只有一個實例的模式。物件字面量先天不具備實例化和繼承的能力,我們接下來還要了解 JavaScript 中另一種建立自訂物件的方法。
函式是 JavaScript 一等公民,就是說其它實體支援的運算子都支援。在 JavaScript 的世界,函數可以在運行時進行動態構造,可以作為參數,也可以作為其它函數的回傳值,也可以被賦予變數。而且,函數也可以擁有自己的屬性和方法。 JavaScript 中函數的特性使之成為可以實體化和繼承的東西。
來看看怎麼用建構子建立一個自訂的物件:
建立建構函式類似建立普通函數,只有一點例外:用this關鍵字定義自發性和方法。一旦函數被創建,就可以用 new 關鍵字產生實例並賦予變數。每次使用 new 關鍵字,this 都指向一個新的實例。
建構函數實例化和傳統物件導向程式語言中的透過類別實例化並非完全不同,但是,這裡存在一個可能不易被察覺的問題。
當使用 new 關鍵字建立新物件的時候,函數區塊會被重複執行,這使得每次運行都會產生新的匿名函數來定義方法。這就像創建新的物件一樣,會導致程式消耗更多記憶體。這個問題在現代瀏覽器上運行的程式中並不顯眼。但隨著應用規則地擴大,在舊一點的瀏覽器、電腦或低電耗設備中就會出現效能問題。不過不用擔心,有更好的方法將方法附加給構造函數(是不會污染全域環境的哦)。
前面介紹中提到 JavaScript 是一種基於原型的程式語言。在 JavaScript 中,可以把原型當作物件模板一樣來使用。原型能避免在實例化物件時創建多餘的匿名函數和變數。
在 JavaScript 中,prototype 是一個非常特別的屬性,可以讓我們為物件新增新的屬性和方法。現在用原型重寫上面的範例看看:
這個範例中,不再為每個 Person 實例定義sayHey 方法,而是透過原型模板在各實例中共享這個方法。
透過原型鏈,原型可以用來實例繼承。 JavaScript 的每個對像都有原型,而原型是另一個對象,也有它自己的原型,周而復始...直到某個原型對象的原型是 null——原型鏈到此為止。
在存取一個方法或屬性的時候,JavaScript 首先檢查它們是否在物件中定義,如果不,則檢查是否定義在原型中。如果在原型中也沒找到,則會延著原型鏈一直找下去,直到找到,或到達原型鏈的終端。
現在來看看程式碼是怎麼實現的。可以從上一個範例中的 Person 物件開始,另外再建立一個叫做 Employee 的物件。
現在 Employee 只有一個屬性。不過既然員工也屬於人,我們希望它能從 Person 繼承其它屬性。要達到這個目的,我們可以在 Employee 物件中呼叫 Person 的建構函數,並配置原型鏈。
要適應原型繼承還需要一些時間,但是這一個必須熟悉的重要概念。雖然原型繼承模型常常被認為是 JavaScript 的弱點,但實際上它比傳統模型更強大。比如說,在掌握了原型模型之後創建傳統模型簡直就太容易了。
ECMAScript 6 引入了一組新的關鍵字用於實作 類別。雖然新的設計看起來與傳統基於類別的開發語言非常接近,但它們並不相同。 JavaScript 仍然基於原型。
JavaScript已經經過了長時間的發展,在此期間,以今天的標準來看,一些不應該使用的方法,卻被大量開發者使用著。根據 ES2015 的介紹,這種狀況正開始慢慢改變,然而,許多開發人員仍然堅持使用一些舊的程式設計方式,這損害了他們的程式碼的關聯性。理解物件導向程式設計方法,並將它應用在你的JavaScript專案中,對於編寫可持續的程式碼非常有意義。
我希望這個簡短的介紹將有助於你達到這個目標。
以上就是JavaScript 中的物件導向程式設計的內容,更多相關內容請關注PHP中文網(www.php.cn)!