精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
在JavaScript中使用面向對象

原文地址:http://www.cnblogs.com/Truly/archive/2007/07/24/830013.html

前言

        OO(面向對象)概念的提出是軟件開發工程發展的一次革命,多年來我們借助它使得很多大型應用程序得以順利實現。如果您還沒有掌握并使用OO進行程序設計和開發,那么您無疑還停留在軟件開發的石器時代。大多數編程語言,尤其是近年問世的一些語言,都很好的支持了面向對象,您可能對此了如執掌,但是一些語言在OO方面卻無法與其它高級語言相比,在這些語言上進行面向對象程序設計和開發會有些困難,例如本文要討論的JavaScript。JavaScript是一門古老的語言,但是隨著近期Web2.0 技術的熱捧,這門語言又重新煥發出青春的光輝,借助于JavaScript客戶端技術,我們的Web體驗變得豐富而又精彩,為了設計和開發更加完善、復雜的客戶端應用,我們必須掌握JavaScript上的OO方法,這正是本文要討論的。 前幾天閱讀了MSDN的《使用面向對象的技術創建高級 Web 應用程序》一文,覺得還有些東西有必要繼續探討補充一下,就有了本文。

        目錄

        開始
        對象的聲明
        成員的聲明
        全局變量和局部變量
        命名空間

開始
JavaScript是一門相當靈活的語言,語法也相當寬松,并且入門門檻很低,您可以不費什么力氣就編寫出一大堆可以運行的代碼,但是根據我在實際工作中的經驗,多數人還是對之核心技術知之甚少。同樣一個功能,簡簡單單幾行代碼,就可看出一個人的技術功底。正如天龍八部中的蕭峰使用的一招“太祖長拳”,這是一種武術中的入門的招法,雖然它看上去很簡單,但是在高手的使用下,卻是威力無窮。其實越是簡單的東西,要把它變得完美就越是困難。所以作為能工巧匠的您怎能錯過這篇文章?切聽我一一道來。

 

對象的聲明
在JavaScript我們可以使用下面幾種代碼進行對象聲明:

Js代碼
  1. var MyObject = {};  

 

 

Js代碼
  1. function MyObject()   
  2. {   
  3.         blabalbla...   
  4. }  

 

 

Js代碼
  1. var MyObject = function(){balbalba...};  

對于后兩種方法,我們還可以增加參數,這樣就類似于一個帶參數的構造器了,例如:

Js代碼
  1. function MyObject(msg)   
  2. {   
  3.         alert(msg);   
  4. }   
  5.   
  6. var o = new MyObject("Hello world");   
  7.   
  8. var MyObject = function(msg)   
  9. {   
  10.       alert(msg + " again");   
  11. };   
  12.   
  13. var o = new MyObject("Hello world!");  

 

甚至我們可以使用字符串來生聲明函數,這使得我們的程序更加靈活:

 

Js代碼
  1. /*  
  2.  * Function可以有多個入口參數,最后一個參數最為方法體。  
  3.  */  
  4. var MyObject = new Function("msg","alert(msg);");   
  5.   
  6. var o = new MyObject("Hello world!");  

 

成員的聲明

在JavaScript中,要聲明一個對象的成員也非常簡單,但是跟其它的高級程序仍然略有不同,請看下面的示例:

Js代碼
  1. var MyObject = {   
  2.       FirstName:"Mary",    
  3.       LastName:"Cook",   
  4.       Age:18,    
  5.       ShowFullName : function(){   
  6.      alert(this.FirstName + ' ' + this.LastName);   
  7.        }   
  8.   }   
  9.      
  10. MyObject.ShowFullName();  

 

或者使用字符串來聲明:

Js代碼
  1. var MyObject = {   
  2.       "FirstName":"Mary",    
  3.       "LastName":"Cook",   
  4.       "Age":18,    
  5.       "ShowFullName" : function(){   
  6.      alert(this.FirstName + ' ' + this.LastName);   
  7.        }   
  8.   }   
  9.      
  10. MyObject.ShowFullName();  

 

 

用字符串的聲明方式有諸多好處,這也是JavaScript中表示對象的一種特殊方式,像近年JSON概念的提出,將這種特殊方式提示到了一個新的高度,更多JSON的介紹請參加我以前的大作《深入淺出JSON》。

而在實際的程序設計中,這種方式在JavaScript的面向對象程序設計中我們通常用來映射數據類型,定義類似高級語言中的結構,集合,實體等,還常常用作定義靜態幫助器類,無需構造而可以直接訪問成員方法。例如上面代碼中的MyObject.ShowFullName();

前面我們介紹了成員的定義,在JavaScript中另一個面向對象特點是我們可以像高級編程語言一樣使用.和[]引用成員,如:

Js代碼
  1. var DateTime = { Now : new Date(), "Show" : function() { alert(new Date());} };   
  2.   
  3. alert(DateTime.Now);   
  4. // 等價于:   
  5. alert(DateTime["Now"]);   
  6.   
  7. DateTime.Show()   
  8. // 等價于:   
  9. DateTime["Show"]();  

 

提到方法調用,這里有一些知識需要知道,在JavaScript中,所有的對象的基類是Object,基類通過prototype定義了很多成員和方法,例如toString, toLocaleString, valueOf
這里我以toString()來做一介紹,請看下面示例:

Js代碼
  1. var obj = { "toString" : function() { return "This is an object."; } };   
  2. alert(obj);  

 

我們注意到當alert的時候,toString()方法被調用了,事實上,當javascript需要將一個對象轉換成字符串時就隱式調用這個對象的toString()方法,例如alert或者document.write或者字符串需要進行+運算等等。參加下面示例代碼:

Js代碼
  1. Date.prototype.toString = function(){ alert('This is called');}   
  2. var dt= new Date(new Date());   
  3.   
  4. Date.prototype.toString = function(){ alert('This is called');}   
  5. var dt= new Date() + 1;  

 

通過這個例子我們驗證了這一點,即使一個對象作為入口參數也可能會調用其toString方法。除了這一點外,該示例同時演示了如何覆蓋基類中定義的方法。

 

全局變量和局部變量

 

在JavaScript中,在全局上下文中聲明的變量作為全局變量,而在對象或方法內部聲明的對象則作為本地變量。請參見下面的代碼:

Js代碼
  1. var global = 1;   
  2. function mm()   
  3. {   
  4.     var global = 2; // 聲明本地變量   
  5.     alert(this.global); // 等價于alert(global);   
  6. }   
  7. mm();   
  8. alert(this.global); // 等價于alert(global);  

 

上面例子我們可以看出本地變量和全局變量即使同名也不會出現沖突。
另外Javascript有一個特性就是變量不用聲明就可以使用,在第一次使用一個未聲明的變量時,系統會自動聲明該變量,并將其作為全局變量。但是在構建大型應用程序的時候,這一點是非常具有破壞性的,如果該變量名在多個腳本塊中出現,引起變量名沖突,導致嚴重的程序錯誤。因此,我們應該盡量避免使用全局變量,并且保持先聲明后使用的良好習慣。

在JavaScript中this關鍵字是比較重要的一個特點,它會隨調用對象而發生改變,始終與當前對象的上下文保持一致,這里一個例子讓我們演示this并且同時繼續深入研究toString,首先我們使用構造器方式創建一個對象,代碼如下:

Js代碼
  1. function obj(params){   
  2. toString = function() { return 'This is an object.'; }   
  3. }    
  4.   
  5. alert(new obj());  

 

你會發現當運行這段代碼的時候,瀏覽器將會拋出一個錯誤。
下面我們再看另外兩段代碼:

Js代碼
  1. function obj(params){   
  2. aMethod = function() { return 'This is global method.'; }   
  3. }    
  4. alert(new obj()); // 正常執行   
  5.   
  6.   
  7. function obj(params){   
  8. this.toString = function() { return 'This is local method.'; }   
  9. }    
  10.   
  11. alert(new obj()); // 正常執行  

 

第一個函數聲明雖沒有使用this關鍵字,這時如果初始化對象那么將聲明一個全局方法aMethod。第二個函數聲明則為對象定義了一個自己的toString()方法。

當分析這兩個函數的時候,你會注意到JavaScript的另一個特性,解釋執行,所以

Js代碼
  1. function obj(params)   
  2. {   
  3.         aMethod = function()   
  4.         {   
  5.                 return 'This is global method.';   
  6.         }   
  7. }   
  8. alert(aMethod()); // 次句會報錯   
  9.   
  10. function obj(params)   
  11. {   
  12.         aMethod = function()   
  13.         {   
  14.                 return 'This is global method.';   
  15.         }   
  16. }   
  17. new obj(); // 實例化的時候,聲明了全局變量阿Method()方法   
  18. alert(aMethod()); // 正常執行  

通過上面的例子我們知道關鍵字this非常重要,如果使用不當,可能會造成全局函數的改變。有一點需要記住,絕不要調用包含“this”(卻沒有所屬對象)的函數。否則,將違反全局命名空間,因為在調用這樣的函數時,“this”將引用全局對象,而這必然會給您的應用程序帶來災難。

如下面的例子,當對象沒有定義this指定的函數(isNaN)時,那么可能覆蓋全局的同名函數,看一些代碼示例:

正確使用this的例子:

Js代碼
  1. alert(isNaN(1)); // 全局函數isNaN   
  2.   
  3. function obj(params)   
  4. {   
  5.         this.toString = function(){return 'This is an object.';};   
  6.         this.isNaN = function()   
  7.         {   
  8.                 return 'not anymore';   
  9.         };   
  10. }   
  11.   
  12. var o = new obj(); // 正確使用方式,調用構造函數   
  13. alert(o.isNaN(1)); // 此時obj定義中的this指向o這個實例而不是全局上下文   
  14. alert(isNaN(1)); // 全局函數未發生變化  

 

錯誤的例子:

Js代碼
  1. alert(isNaN(1)); // 全局函數isNaN   
  2.   
  3. function obj(params)   
  4. {   
  5.         isNaN = function()   
  6.         {   
  7.                 return 'not anymore';   
  8.         }   
  9. }   
  10.   
  11. obj(); // 錯誤的使用方式,this指向全局上下文,全局函數isNaN被覆蓋   
  12. alert(isNaN(1)); // 全局函數發生改變  

 

同時我們還注意到有一些全局函數則無法覆蓋,例如toString()

下面我們看JavaScript的一個很好用的方法:call

 

關于call的解釋:

call方法可以用來代替另一個對象調用一個方法。call方法可以將一個函數的對象上下文從初始化的上下文改變為由thisObj指定的新對象。

可以這樣來理解:

我們定義了一個函數abc:

Js代碼
  1. function abc()   
  2. {   
  3.         alert(this.member1);   
  4. }   
  5.   
  6. var obj = {member1:"Hello world!",show:abc};   
  7. var obj2 = {member1:"Hello world again!",show:abc};   
  8.   
  9. obj.show();   
  10.   
  11. // 也可以使用   
  12. abc.call(obj);   
  13. abc.call(obj2);  

 

修改后的另一個版本:

Js代碼
  1. member1 = 'test';   
  2.   
  3. function abc()   
  4. {   
  5.         alert(this.member1);   
  6. }   
  7.   
  8. var obj = { member1:"Hello world", show:abc};   
  9. var obj2 = { member1:"Hello world again", show:abc};   
  10.   
  11. obj.show();   
  12.   
  13. // 也可以使用   
  14. abc.call(obj);   
  15. abc.call(obj2);   
  16.   
  17. abc(); // 此時abc中的this指向了當前上下文  

 

每個函數都有call方法,上面的過程中我們看到用另一個對象代替調用顯示方法,并且注意到this在對象上下文中的改變。

通過上面基礎知識的研究,讓我們再向前跨出一步,使用call的特性來實現類的繼承,參見下面的示例:

Js代碼
  1. // 統一類構造器   
  2. function MyClassInitor()   
  3. {   
  4.         this.base();   
  5.         if(!this.mm)   
  6.         {   
  7.                 alert('未定義成員函數:mm()');   
  8.         }   
  9.   
  10.         return this;   
  11. }   
  12.   
  13. // 定義一個基類   
  14. function baseClass()   
  15. {   
  16.         if(!this.tt) // 判斷該成員是否被繼承類覆蓋   
  17.      {   
  18.                 this.tt = '基類成員';   
  19.         }   
  20. }   
  21.   
  22. // 從基類繼承   
  23. var obj = { member1:"Hello world", base:baseClass, gg:function(){ alert('I am an GG');}};   
  24.   
  25. var obj2 = { member1:"Hello world again", base:baseClass,mm:function(name){alert('I am MM '+name + '.');}, tt:"覆蓋基類的tt成員"};   
  26.   
  27. var o = MyClassInitor.call(obj);   
  28. var o2 = MyClassInitor.call(obj2);   
  29.   
  30. alert(o.tt);   
  31. alert(o2.tt);   
  32.   
  33. o2.mm('Mary');  

 

雖然跟高級編程語言的語法有點不同,但是你必須了解JavaScript的語法特點。通過這個例子,我們什么分析了thiscall的配合,但是實際進行類繼承設計時往往不會采用此方法進行實現,后面我們介紹Prototype時再做詳細介紹。

 

命名空間

前面我們了解完類、對象的聲明,下面看一下Javascript中命名空間的處理,大家知道,在高級編程語言中我們非常熟練的使用命名空間來避免變量或方法名的沖突,那么同樣我們也可以在JavaScript中使用命名空間來為我們的類和方法進行界定。在JavaScript中命名空間的聲明與其它高級語言略有不同,下面是一個命名空間聲明的示例:

Js代碼
  1. var System = {};   
  2. var System.Web = {};  

 

通過這兩行代碼我們就有了System和System.Web兩個命名空間,回想一下前面我們介紹的知識,你很快可以發現,這是兩個對象聲明語句。在JavaScript中,我們正是使用對象來表示命名空間的。但是你必須清楚一點,由于JavaScript的特性,在實際應用中,我們不能這么簡單的來處理命名空間,因為聲明語句可能同時出現在多個地方或者多個js文件中,我們知道,在JavaScript中,最后聲明的變量會覆蓋前面同名的變量,因此通常我們要加一些判斷代碼來防止重復聲明,例如:

Js代碼
  1. if(typeof System == 'undefined'var System = {};  

 

這樣即使這段代碼在程序中重復出現多次我們也可以保證System對象只聲明一次。關于這一點,大家如果深入研究過AjaxPro和其它很多大型JavaScript框架,會發現當配合后端應用程序的時候,它是多么的有用。例如AjaxPro的類型注冊,關于AjaxPro可參見我另一篇文章《AjaxPro框架剖析》。

本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
js立即執行函數
JavaScript 的 this 原理
JavaScript代碼不好讀,不好維護?你需要改變寫代碼的習慣
javascript深入理解js閉包
淺談js之閉包
詳解JS中定時器setInterval和setTImeout的this指向問題
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 大埔县| 汉源县| 阜阳市| 昆明市| 成都市| 平邑县| 彰化市| 和平区| 仁布县| 二连浩特市| 新野县| 海城市| 海阳市| 宝鸡市| 克山县| 思茅市| 二手房| 徐州市| 兴安县| 陇西县| 克什克腾旗| 中卫市| 黑龙江省| 虞城县| 阳山县| 安多县| 温宿县| 尚义县| 洪洞县| 柳河县| 民丰县| 贡嘎县| 类乌齐县| 板桥市| 阜平县| 冷水江市| 梓潼县| 沙洋县| 灵寿县| 临潭县| 平阴县|