JAVA & XML & JAVASCRIPT & AJAX & CSS

          Web 2.0 技術儲備............

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            77 隨筆 :: 17 文章 :: 116 評論 :: 0 Trackbacks

          轉自 : http://www.bjcan.com/hengxing/readlou.asp?id=1162

          八、JavaScript面向對象的支持
          ~~~~~~~~~~~~~~~~~~
          很少有人對JavaScript的面向對象特性進行系統的分析。我希望接下來的文字讓你了解到這
          個語言最少為人知的一面。


          1. JavaScript中的類型
          --------
          雖然JavaScript是一個基于對象的語言,但對象(Object)在JavaScript中不是第一型的。JS
          是以函數(Function)為第一型的語言。這樣說,不但是因為JS中的函數具有高級語言中的函
          數的各種特性,而且也因為在JS中,Object也是由函數來實現的。——關于這一點,可以在
          后文中“構造與析構”部分看到更進一步的說明。

          JS中是弱類型的,他的內置類型簡單而且清晰:
          ---------------------------------------------------------
          undefined : 未定義
          number??? : 數字
          boolean?? : 布爾值
          string??? : 字符串
          function? : 函數
          object??? : 對象

          ?1). undefined類型
          ========================
          在IE5及以下版本中,除了直接賦值和typeof()之外,其它任何對undefined的操作都將導致
          異常。如果需要知道一個變量是否是undefined,只能采用typeof()的方法:
          <script>
          var v;
          if (typeof(v) == 'undefined') {
          ? // ...
          }
          </script>

          但是在IE5.5及以上版本中,undefined是一個已實現的系統保留字。因此可以用undefined來
          比較和運算。檢測一個值是否是undefined的更簡單方法可以是:
          <script>
          var v;
          if (v === undefined) {
          ? // ...
          }
          </script>

          因此為了使得核心代碼能(部分地)兼容IE5及早期版本,Romo核心單元中有一行代碼用來
          “聲明”一個undefined值:
          //---------------------------------------------------------
          // code from Qomolangma, in JSEnhance.js
          //---------------------------------------------------------
          var undefined = void null;

          這一行代碼還有一點是需要說明的,就是void語句的應用。void表明“執行其后的語句,且
          忽略返回值”。因此在void之后可以出現能被執行的任何“單個”語句。而執行的結果就是
          undefined。當然,如果你愿意,你也可以用下面的代碼之一“定義undefined”。
          //---------------------------------------------------------
          // 1. 較復雜的方法,利用一個匿名的空函數執行的返回
          //---------------------------------------------------------
          var undefined = function(){}();

          //---------------------------------------------------------
          // 2. 代碼更簡潔,但不易懂的方法
          //---------------------------------------------------------
          var undefined = void 0;

          void也能像函數一樣使用,因此void(0)也是合法的。有些時候,一些復雜的語句可能不能
          使用void的關鍵字形式,而必須要使用void的函數形式。例如:
          //---------------------------------------------------------
          // 必須使用void()形式的復雜表達式
          //---------------------------------------------------------
          void(i=1);?????? // 或如下語句:
          void(i=1, i++);


          ?2). number類型
          ========================
          JavaScript中總是處理浮點數,因此它沒有象Delphi中的MaxInt這樣的常量,反而是有這
          樣兩個常值定義:
          ? Number.MAX_VALUE? : 返回 JScript 能表達的最大的數。約等于 1.79E+308。
          ? Number.MIN_VALUE? : 返回 JScript 最接近0的數。約等于 2.22E-308。

          因為沒有整型的緣故,因此在一些關于CSS和DOM屬性的運算中,如果你期望取值為整數2,
          你可能會得到字符串“2.0”——或者類似于此的一些情況。這種情況下,你可能需要用
          到全局對象(Gobal)的parseInt()方法。

          全局對象(Gobal)中還有兩個屬性與number類型的運算有關:
          ? NaN????? : 算術表達式的運算結果不是數字,則返回NaN值。
          ? Infinity : 比MAX_VALUE更大的數。

          如果一個值是NaN,那么他可以通過全局對象(Gobal)的isNaN()方法來檢測。然而兩個NaN
          值之間不是互等的。如下例:
          //---------------------------------------------------------
          // NaN的運算與檢測
          //---------------------------------------------------------
          var
          ? v1 = 10 * 'a';
          ? v2 = 10 * 'a';
          document.writeln(isNaN(v1));
          document.writeln(isNaN(v2));
          document.writeln(v1 == v2);

          全局對象(Gobal)的Infinity表示比最大的數 (Number.MAX_VALUE) 更大的值。在JS中,
          它在數學運算時的價值與正無窮是一樣的。——在一些實用技巧中,它也可以用來做一
          個數組序列的邊界檢測。

          Infinity在Number對象中被定義為POSITIVE_INFINITY。此外,負無窮也在Number中被定
          義:
          ? Number.POSITIVE_INFINITY? : 比最大正數(Number.MAX_VALUE)更大的值。正無窮。
          ? Number.NEGATIVE_INFINITY? : 比最小負數(-Number.MAX_VALUE)更小的值。負無窮。

          與NaN不同的是,兩個Infinity(或-Infinity)之間是互等的。如下例:
          //---------------------------------------------------------
          // Infinity的運算與檢測
          //---------------------------------------------------------
          var
          ? v1 = Number.MAX_VALUE * 2;
          ? v2 = Number.MAX_VALUE * 3;
          document.writeln(v1);
          document.writeln(v2);
          document.writeln(v1 == v2);

          在Global中其它與number類型相關的方法有:
          ?isFinite()?? : 如果值是NaN/正無窮/負無窮,返回false,否則返回true。
          ?parseFloat() : 從字符串(的前綴部分)取一個浮點數。不成功則返回NaN。


          ?3). boolean類型
          ========================
          ?(略)

          ?4). string類型
          ========================
          JavaScript中的String類型原本沒有什么特殊的,但是JavaScript為了適應
          “瀏覽器實現的超文本環境”,因此它具有一些奇怪的方法。例如:
          ? link() : 把一個有HREF屬性的超鏈接標簽<A>放在String對象中的文本兩端。
          ? big()? : 把一對<big>標簽放在String對象中的文本兩端。
          以下方法與此類同:
          ? anchor()
          ? blink()
          ? bold()
          ? fixed()
          ? fontcolor()
          ? fontsize()
          ? italics()
          ? small()
          ? strike()
          ? sub()
          ? sup()

          除此之外,string的主要復雜性來自于在JavaScript中無所不在的toString()
          方法。這也是JavaScript為瀏覽器環境而提供的一個很重要的方法。例如我們
          聲明一個對象,但是要用document.writeln()來輸出它,在IE中會顯示什么呢?

          下例說明這個問題:
          //---------------------------------------------------------
          // toString()的應用
          //---------------------------------------------------------
          var
          ? s = new Object();

          s.v1 = 'hi,';
          s.v2 = 'test!';
          document.writeln(s);
          document.writeln(s.toString());

          s.toString = function() {
          ? return s.v1 + s.v2;
          }
          document.writeln(s);

          在這個例子中,我們看到,當一個對象沒有重新聲明(覆蓋)自己toString()方
          法的時候,那么它作為字符串型態使用時(例如被writeln),就會調用Java Script
          環境缺省的toString()。反過來,你也可以重新定義JavaScript理解這個對象
          的方法。

          很多JavaScript框架,在實現“模板”機制的時候,就利用了這個特性。例如
          他們用這樣定義一個FontElement對象:
          //---------------------------------------------------------
          // 利用toString()實現模板機制的簡單原理
          //---------------------------------------------------------
          function FontElement(innerHTML) {
          ? this.face = '宋體';
          ? this.color = 'red';
          ? // more...

          ? var ctx = innerHTML;
          ? this.toString = function() {
          ??? return '<Font FACE="' + this.face + '" COLOR="' + this.color + '">'
          ????? + ctx
          ????? + '</FONT>';
          ? }
          }

          var obj = new FontElement('這是一個測試。');

          // 留意下面這行代碼的寫法
          document.writeln(obj);


          ?5). function類型
          ========================
          javascript函數具有很多特性,除了面向對象的部分之外(這在后面講述),它自
          已的一些獨特特性應用也很廣泛。

          首先javascript中的每個函數,在調用過程中可以執有一個arguments對象。這個
          對象是由腳本解釋環境創建的,你沒有別的方法來自己創建一個arguments對象。

          arguments可以看成一個數組:它有length屬性,并可以通過arguments[n]的方式
          來訪問每一個參數。然而它最重要的,卻是可以通過 callee 屬性來得到正在執行
          的函數對象的引用。

          接下的問題變得很有趣:Function對象有一個 caller 屬性,指向正在調用當前
          函數的父函數對象的引用。

          ——我們已經看到,我們可以在JavaScript里面,通過callee/caller來遍歷執行
          期的調用棧。由于arguments事實上也是Function的一個屬性,因此我們事實上也
          能遍歷執行期調用棧上的每一個函數的參數。下面的代碼是一個簡單的示例:

          //---------------------------------------------------------
          // 調用棧的遍歷
          //---------------------------------------------------------
          function foo1(v1, v2) {
          ? foo2(v1 * 100);
          }

          function foo2(v1) {
          ? foo3(v1 * 200);
          }

          function foo3(v1) {
          ? var foo = arguments.callee;
          ? while (foo && (foo != window)) {
          ??? document.writeln('調用參數:<br>', '---------------<br>');

          ??? var args = foo.arguments, argn = args.length;
          ??? for (var i=0; i<argn; i++) {
          ????? document.writeln('args[', i, ']: ', args[i], '<br>');
          ??? }
          ??? document.writeln('<br>');

          ??? // 上一級
          ??? foo = foo.caller;
          ? }
          }

          // 運行測試
          foo1(1, 2);


          2. JavaScript面向對象的支持
          --------
          在前面的例子中其實已經講到了object類型的“類型聲明”與“實例創建”。
          在JavaScript中,我們需要通過一個函數來聲明自己的object類型:
          //---------------------------------------------------------
          // JavaScript中對象的類型聲明的形式代碼
          // (以后的文檔中,“對象名”通常用MyObject來替代)
          //---------------------------------------------------------
          function 對象名(參數表) {
          ? this.屬性 = 初始值;

          ? this.方法 = function(方法參數表) {
          ??? // 方法實現代碼
          ? }
          }


          然后,我們可以通過這樣的代碼來創建這個對象類型的一個實例:
          //---------------------------------------------------------
          // 創建實例的形式代碼
          // (以后的文檔中,“實例變量名”通常用obj來替代)
          //---------------------------------------------------------
          var 實例變量名 = new 對象名(參數表);


          接下來我們來看“對象”在JavaScript中的一些具體實現和奇怪特性。

          ?1). 函數在JavaScript的面向對象機制中的五重身份
          ?------
          “對象名”——如MyObject()——這個函數充當了以下語言角色:
          ? (1) 普通函數
          ? (2) 類型聲明
          ? (3) 類型的實現
          ? (4) 類引用
          ? (5) 對象的構造函數

          一些程序員(例如Delphi程序員)習慣于類型聲明與實現分開。例如在delphi
          中,Interface節用于聲明類型或者變量,而implementation節用于書寫類型
          的實現代碼,或者一些用于執行的函數、代碼流程。

          但在JavaScript中,類型的聲明與實現是混在一起的。一個對象的類型(類)
          通過函數來聲明,this.xxxx表明了該對象可具有的屬性或者方法。


          這個函數的同時也是“類引用”。在JavaScript,如果你需要識別一個對象
          的具體型別,你需要執有一個“類引用”。——當然,也就是這個函數的名
          字。instanceof 運算符就用于識別實例的類型,我們來看一下它的應用:
          //---------------------------------------------------------
          // JavaScript中對象的類型識別
          //?? 語法:? 對象實例 instanceof 類引用
          //---------------------------------------------------------
          function MyObject() {
          ? this.data = 'test data';
          }

          // 這里MyObject()作為構造函數使用
          var obj = new MyObject();
          var arr = new Array();

          // 這里MyObject作為類引用使用
          document.writeln(obj instanceof MyObject);
          document.writeln(arr instanceof MyObject);

          ================
          (未完待續)
          ================
          接下來的內容:

          2. JavaScript面向對象的支持
          --------

          ?2). 反射機制在JavaScript中的實現
          ?3). this與with關鍵字的使用
          ?4). 使用in關鍵字的運算
          ?5). 使用instanceof關鍵字的運算
          ?6). 其它與面向對象相關的關鍵字

          3. 構造與析構

          4. 實例和實例引用

          5. 原型問題

          6. 函數的上下文環境

          7. 對象的類型檢查問題

          ?

          posted on 2006-03-20 09:40 Web 2.0 技術資源 閱讀(411) 評論(0)  編輯  收藏 所屬分類: Javascript
          主站蜘蛛池模板: 宜州市| 灵丘县| 会同县| 吉木萨尔县| 茶陵县| 安丘市| 和田县| 疏附县| 盱眙县| 桂林市| 海城市| 吉隆县| 吐鲁番市| 沙坪坝区| 广安市| 赤壁市| 江山市| 道孚县| 定兴县| 柘荣县| 搜索| 泗水县| 宁强县| 张家港市| 合山市| 嘉峪关市| 江都市| 延津县| 南乐县| 重庆市| 修水县| 肥城市| 寿宁县| 鸡西市| 淮安市| 漾濞| 扶风县| 阳西县| 逊克县| 麦盖提县| 凤冈县|