摘 要:本文從經(jīng)典的面向?qū)ο缶幊痰幕局R入手,通過分析JavaScript面向?qū)ο蟛灰粯拥牡胤?,進一步對如何能夠?qū)懗隹删S護的面向?qū)ο蟮腏avaScript 代碼進行了相關(guān)研究。
關(guān)鍵詞:面向?qū)ο?;JavaScript;類;繼承;重用
中圖分類號:TP311.10
寫出可維護的面向?qū)ο蟮腏avaScript代碼不僅節(jié)約時間,還讓自已享受重用代碼的過程。對于每一位從事JavaScript代碼編寫的人員來說,如何編寫可重用的代碼都成為其追求的目標。在開始探究如何編寫可維護的面向?qū)ο驤avaScript代碼之前,先來看看什么是面向?qū)ο蟆?/p>
1 面向?qū)ο?/p>
面向?qū)ο缶幊讨饕ㄟ^代碼代表現(xiàn)實世界中的實質(zhì)對象。要創(chuàng)建對象,首先需要寫一個“類”來定義。類可以代表所有的東西,而每次要創(chuàng)建對象的時候,就從類實例化一個對象。對象實質(zhì)上是數(shù)據(jù)的容器,對象包括處理數(shù)據(jù)的函數(shù)(也叫“方法”)。方法被用作媒介來確保數(shù)據(jù)的完整性,以及在儲存之前對數(shù)據(jù)進行轉(zhuǎn)換。最后,類還可以繼承其他的類,繼承可以在不同類中重復使用相同代碼。
2 JavaScript面向?qū)ο蟛灰粯?/p>
上面概述了經(jīng)典的面向?qū)ο缶幊痰幕局R。說經(jīng)典是因為JavaScript并不遵循這些規(guī)則。相反地,JavaScript的類是寫成函數(shù)的樣子,而繼承則是通過原型實現(xiàn)的。原型繼承意味著使用原型屬性來實現(xiàn)對象的繼承,而不是從類繼承。
2.1 對象的實例化
以下是 JavaScript 中對象實例化的例子:
// 定義 Employee 類
function Employee (num, fname, lname) {this.getFullName = function () {
return fname + \" \" + lname;}};
// 實例化 Employee 對象
var john = new Employee (\"4815162342\", \"John\", \"Doe\");
alert (\"The employee's full name is \" + john.getFullName ());
在這里,有三點要注意:
(1)“class”函數(shù)名的第一個字母要大寫。表明該函數(shù)是被實例化。
(2)在實例化時使用了new操作符。
(3)因為getFullName指定給this操作符了,所以是公共的,但是fname和lname則不是。
2.2 原型繼承
下面是JavaScript中原型繼承的例子:// 定義Human類
function Human () {this.setName = function (fname, lname) {
this.fname = fname; this.lname = lname; }
this.getFullName = function () {
return this.fname + \" \" + this.lname; } }
// 定義 Employee 類
function Employee (num) {this.getNum = function () {return num; }};
//讓 Employee 繼承 Human 類
Employee.prototype = new Human ();
// 實例化 Employee 對象
var john = new Employee (\"4815162342\");
john.setName (\"John\", \"Doe\");
alert (john.getFullName () + \"'s employee number is \" + john.getNum ());
這次,創(chuàng)建的Human類包含人類的一切共有屬性,將fname和lname放進去,因為不僅員工才有名字,所有人都有名字。然后將Human對象賦值給它的prototype屬性。
2.3 通過繼承實現(xiàn)代碼重用
在上面的例子中,原來的Employee類被分解成兩部分。所有的人類通用屬性被移到了Human類中,然后讓Employee繼承Human。這樣,Human里的屬性就可以被其他對象使用,例如Student(學生),Client(顧客),Citizen(公民),Visitor(游客)等,這是分割和重用代碼較好的方式。
2.4 Public(公有的)和Private(私有的)
根據(jù)對象中處理數(shù)據(jù)的方式不同,數(shù)據(jù)會被處理為私有的或者公有的。私有屬性并不一定意味著其他人無法訪問,只是某個方法需要用到。
2.5 只讀
有時,只想在創(chuàng)建對象的時候有一個值。一旦創(chuàng)建,就不想再改變??梢詣?chuàng)建一個私有變量,在實例化的時候給它賦值。
function Animal (type) {
var data = []; data['type'] = type; this.getType = function () {
return data['type'];}}
var fluffy = new Animal ('dog');
fluffy.getType (); // 返回 'dog'
此例中,Animal類中創(chuàng)建了一個本地數(shù)組data。當Animal對象被實例化時,傳遞了一個type的值并將其放在data數(shù)組中。因為它是私有的,所以該值無法被覆蓋,雖可以讀到對象的類型卻無法改變。
有一點非常重要,就是當對象被繼承時,“只讀”技術(shù)就無法運用。在執(zhí)行繼承后,每個實例化的對象都會共享那些只讀變量并覆蓋其值。最簡單的解決辦法是將類中的只讀變量轉(zhuǎn)換成公共變量,但必須保持它們是私有的。
2.6 Public(公有)
當然也有時候想任意讀寫某個屬性的值。要實現(xiàn)這一點,需要使用this操作符。
function Animal () { this.mood = ''; }
var fluffy = new Animal ();
fluffy.mood = 'happy';
fluffy.mood; // 返回 'happy'
這次Animal類公開了一個叫mood的屬性,可以被隨意讀寫。同樣地,還可以將函數(shù)指定給公有的屬性,例如之前例子中的getType函數(shù)。只要注意不要給getType賦值。
2.7 完全私有
最后,可能發(fā)現(xiàn)需要一個完全私有化的本地變量。這樣,可以使用與第一個例子中一樣的模式而不需要創(chuàng)建公有方法。
function Animal () { var secret = \"You'll never know!\" }
var fluffy = new Animal ();
2.8 寫靈活的API
既然提到類的創(chuàng)建,為了保持與產(chǎn)品需求變化同步,需要保持代碼不過時。盡管準確預測未來是不大可能,但是卻完全可以將代碼寫靈活以備將來不時之需。
2.9 讓代碼可嵌入
隨著時間流逝,產(chǎn)品需求可能對類的行為有更多的要求。而該行為卻與類的核心功能沒有關(guān)系。也有可能是類的唯一實現(xiàn),你可能想把一些功能放在類的里面,但是它們不屬于那里,唯一可行的方法是,允許將行為嵌入到代碼當中。JavaScript庫可以足夠容易地做到這一點。
3 總結(jié)
如果打算重用代碼,無論是在同一網(wǎng)頁,同一網(wǎng)站還是跨項目操作,考慮一下在類里面將其打包和組織起來。面向?qū)ο驤avaScript很自然地幫助實現(xiàn)更好的代碼組織以及代碼重用。除此以外,還應(yīng)該有遠見的確保代碼具有足夠的靈活性,可以在寫完代碼后持續(xù)使用很長時間。編寫可重用的JavaScript 代碼可以大大節(jié)省代碼編寫者、開發(fā)團隊和企業(yè)的開發(fā)時間。
參考文獻:
[1]Bruce Eckel.《Think In Jave》中文版[OL].http://wenku.baidu.com/.
[2]劉正林.Java技術(shù)基礎(chǔ)[M].武漢:華中科技大學出版社,2002.
[3]http://scholar.ilib.cn/Abstract.aspx?A=jsjgcyyy200422033.
作者簡介:李超(1979-),男,貴州省遵義市人,高校講師,軟件工程碩士,主要研究領(lǐng)域:計算機應(yīng)用、計算機網(wǎng)絡(luò),計算機輔助設(shè)計。