Java應(yīng)用:編寫高級(jí)JavaScript應(yīng)用代碼

          1、創(chuàng)建高級(jí)對(duì)象

          使用構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象

          構(gòu)造函數(shù)是一個(gè)函數(shù),調(diào)用它來(lái)例示并初始化特殊類型的對(duì)象。可以使用 new 關(guān)鍵字來(lái)調(diào)用一個(gè)構(gòu)造函數(shù)。下面給出了使用構(gòu)造函數(shù)的新示例。

          var myObject = new Object(); // 創(chuàng)建沒有屬性的通用對(duì)象。

          var myBirthday = new Date(1961, 5, 10); // 創(chuàng)建一個(gè) Date 對(duì)象。

          var myCar = new Car(); // 創(chuàng)建一個(gè)用戶定義的對(duì)象,并初始化其屬性。

          通過(guò)構(gòu)造函數(shù)將一個(gè)參數(shù)作為特定的 this 關(guān)鍵字的值傳遞給新創(chuàng)建的空對(duì)象。然后構(gòu)造函數(shù)負(fù)責(zé)為新對(duì)象執(zhí)行適應(yīng)的初始化(創(chuàng)建屬性并給出其初始值)。完成后,構(gòu)造函數(shù)返回它所構(gòu)造的對(duì)象的一個(gè)參數(shù)。

          編寫構(gòu)造函數(shù)

          可以使用 new 運(yùn)算符結(jié)合像 Object()、Date() 和 Function() 這樣的預(yù)定義的構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象并對(duì)其初始化。面向?qū)ο蟮木幊唐鋸?qiáng)有力的特征是定義自定義構(gòu)造函數(shù)以創(chuàng)建腳本中使用的自定義對(duì)象的能力。創(chuàng)建了自定義的構(gòu)造函數(shù),這樣就可以創(chuàng)建具有已定義屬性的對(duì)象。下面是自定義函數(shù)的示例(注意 this 關(guān)鍵字的使用)。

          function Circle (xPoint, yPoint, radius) {

          this.x = xPoint; // 圓心的 x 坐標(biāo)。

          this.y = yPoint; // 圓心的 y 坐標(biāo)。

          this.r = radius; // 圓的半徑。

          }

          調(diào)用 Circle 構(gòu)造函數(shù)時(shí),給出圓心點(diǎn)的值和圓的半徑(所有這些元素是完全定義一個(gè)獨(dú)特的圓對(duì)象所必需的)。結(jié)束時(shí) Circle 對(duì)象包含三個(gè)屬性。下面是如何例示 Circle 對(duì)象。

          var aCircle = new Circle(5, 11, 99);

          使用原型來(lái)創(chuàng)建對(duì)象

          在編寫構(gòu)造函數(shù)時(shí),可以使用原型對(duì)象(它本身是所有構(gòu)造函數(shù)的一個(gè)屬性)的屬性來(lái)創(chuàng)建繼承屬性和共享方法。原型屬性和方法將按引用復(fù)制給類中的每個(gè)對(duì)象,因此它們都具有相同的值。可以在一個(gè)對(duì)象中 更改原型屬性的值,新的值將覆蓋默認(rèn)值,但僅在該實(shí)例中有效。屬于這個(gè)類的其他對(duì)象不受此更改的影響。下面給出了使用自定義構(gòu)造函數(shù)的示例,Circle(注意 this 關(guān)鍵字的使用)。

          Circle.prototype.pi = Math.PI;

          function ACirclesArea () {

          return this.pi * this.r * this.r; // 計(jì)算圓面積的公式為 ?r2。

          }

          Circle.prototype.area = ACirclesArea; // 計(jì)算圓面積的函數(shù)現(xiàn)在是 Circle Prototype 對(duì)象的一個(gè)方法。

          var a = ACircle.area(); // 此為如何在 Circle 對(duì)象上調(diào)用面積函數(shù)。

          使用這個(gè)原則,可以給預(yù)定義的構(gòu)造函數(shù)(都具有原型對(duì)象)定義附加屬性。例如,如果想要能夠刪除字符串的前后空格(與 VBScript 的 Trim 函數(shù)類似),就可以給 String 原型對(duì)象創(chuàng)建自己的方法。

          // 增加一個(gè)名為 trim 的函數(shù)作為

          // String 構(gòu)造函數(shù)的原型對(duì)象的一個(gè)方法。

          String.prototype.trim = function()

          {

          // 用正則表達(dá)式將前后空格

          // 用空字符串替代。

          return this.replace(/(^\s*)|(\s*$)/g, "");

          }

          // 有空格的字符串

          var s = " leading and trailing spaces ";

          // 顯示 " leading and trailing spaces (35)"

          window.alert(s + " (" + s.length + ")");

          // 刪除前后空格

          s = s.trim();

          // 顯示"leading and trailing spaces (27)"

          window.alert(s + " (" + s.length + ")");

          2.遞歸

          遞歸是一種重要的編程技術(shù)。該方法用于讓一個(gè)函數(shù)從其內(nèi)部調(diào)用其自身。一個(gè)示例就是計(jì)算階乘。0 的階乘被特別地定義為 1。 更大數(shù)的階乘是通過(guò)計(jì)算 1 * 2 * ...來(lái)求得的,每次增加 1,直至達(dá)到要計(jì)算其階乘的那個(gè)數(shù)。

          下面的段落是用文字定義的計(jì)算階乘的一個(gè)函數(shù)。

          “如果這個(gè)數(shù)小于零,則拒絕接收。如果不是一個(gè)整數(shù),則將其向下舍入為相鄰的整數(shù)。如果這個(gè)數(shù)為 0,則其階乘為 1。如果這個(gè)數(shù)大于 0,則將其與相鄰較小的數(shù)的階乘相乘。”

          要計(jì)算任何大于 0 的數(shù)的階乘,至少需要計(jì)算一個(gè)其他數(shù)的階乘。用來(lái)實(shí)現(xiàn)這個(gè)功能的函數(shù)就是已經(jīng)位于其中的函數(shù);該函數(shù)在執(zhí)行當(dāng)前的這個(gè)數(shù)之前,必須調(diào)用它本身來(lái)計(jì)算相鄰的較小數(shù)的階乘。這就是一個(gè)遞歸示例。

          遞歸和迭代(循環(huán))是密切相關(guān)的 ? 能用遞歸處理的算法也都可以采用迭代,反之亦然。確定的算法通常可以用幾種方法實(shí)現(xiàn),您只需選擇最自然貼切的方法,或者您覺得用起來(lái)最輕松的一種即可。

          顯然,這樣有可能會(huì)出現(xiàn)問(wèn)題。可以很容易地創(chuàng)建一個(gè)遞歸函數(shù),但該函數(shù)不能得到一個(gè)確定的結(jié)果,并且不能達(dá)到一個(gè)終點(diǎn)。這樣的遞歸將導(dǎo)致計(jì)算機(jī)執(zhí)行一個(gè)“無(wú)限”循環(huán)。下面就是一個(gè)示例:在計(jì)算階乘的文字描述中遺漏了第一條規(guī)則(對(duì)負(fù)數(shù)的處理) ,并試圖計(jì)算任何負(fù)數(shù)的階乘。這將導(dǎo)致失敗,因?yàn)榘错樞蛴?jì)算 -24 的階乘時(shí),首先不得不計(jì)算 -25 的階乘;然而這樣又不得不計(jì)算 -26 的階乘;如此繼續(xù)。很明顯,這樣永遠(yuǎn)也不會(huì)到達(dá)一個(gè)終止點(diǎn)。

          因此在設(shè)計(jì)遞歸函數(shù)時(shí)應(yīng)特別仔細(xì)。如果懷疑其中存在著無(wú)限遞歸的可能,則可以讓該函數(shù)記錄它調(diào)用自身的次數(shù)。如果該函數(shù)調(diào)用自身的次數(shù)太多,即使您已決定了它應(yīng)調(diào)用多少次,就自動(dòng)退出。

          下面仍然是階乘函數(shù),這次是用 JScript 代碼編寫的。

          // 計(jì)算階乘的函數(shù)。如果傳遞了

          // 無(wú)效的數(shù)值(例如小于零),

          // 將返回 -1,表明發(fā)生了錯(cuò)誤。若數(shù)值有效,

          // 把數(shù)值轉(zhuǎn)換為最相近的整數(shù),并

          // 返回階乘。

          function factorial(aNumber) {

          aNumber = Math.floor(aNumber); // 如果這個(gè)數(shù)不是一個(gè)整數(shù),則向下舍入。

          if (aNumber < 0) { // 如果這個(gè)數(shù)小于 0,拒絕接收。

          return -1;

          }

          if (aNumber == 0) { // 如果為 0,則其階乘為 1。

          return 1;

          }

          else return (aNumber * factorial(aNumber - 1)); // 否則,遞歸直至完成。

          }

          3.變量范圍

          JScript 有兩種變量范圍:全局和局部。如果在任何函數(shù)定義之外聲明了一個(gè)變量,則該變量為全局變量,且該變量的值在整個(gè)持續(xù)范圍內(nèi)都可以訪問(wèn)和修改。如果在函數(shù)定義內(nèi)聲明了一個(gè)變量,則該變量為局部變量。每次執(zhí)行該函數(shù)時(shí)都會(huì)創(chuàng)建和破壞該變量;且它不能被該函數(shù)外的任何事物訪問(wèn)。

          像 C++ 這樣的語(yǔ)言也有“塊范圍”。在這里,任何一對(duì)“{}”都定義新的范圍。JScript 不支持塊范圍。

          一個(gè)局部變量的名稱可以與某個(gè)全局變量的名稱相同,但這是完全不同和獨(dú)立的兩個(gè)變量。因此,更改一個(gè)變量的值不會(huì)影響另一個(gè)變量的值。在聲明局部變量的函數(shù)內(nèi),只有該局部變量有意義。

          var aCentaur = "a horse with rider,"; // aCentaur 的全局定義。

          // JScript 代碼,為簡(jiǎn)潔起見有省略。

          function antiquities() // 在這個(gè)函數(shù)中聲明了一個(gè)局部 aCentaur 變量。

          {

          // JScript 代碼,為簡(jiǎn)潔起見有省略。

          var aCentaur = "A centaur is probably a mounted Scythian warrior";

          // JScript 代碼,為簡(jiǎn)潔起見有省略。

          aCentaur += ", misreported; that is, "; // 添加到局部變量。

          // JScript 代碼,為簡(jiǎn)潔起見有省略。

          } // 函數(shù)結(jié)束。

          var nothinginparticular = antiquities();

          aCentaur += " as seen from a distance by a naive innocent.";

          /*

          在函數(shù)內(nèi),該變量的值為 "A centaur is probably a mounted Scythian warrior,

          misreported; that is, ";在函數(shù)外,該變量的值為這句話的其余部分:

          "a horse with rider, as seen from a distance by a naive innocent."

          */

          很重要的一點(diǎn)是注意變量是否是在其所屬范圍的開始處聲明的。有時(shí)這會(huì)導(dǎo)致意想不到的情況。

          tweak();

          var aNumber = 100;

          function tweak() {

          var newThing = 0; // 顯式聲明 newThing 變量。

          // 本語(yǔ)句將未定義的變量賦給 newThing,因?yàn)橐延忻麨?aNumber 的局部變量。

          newThing = aNumber;

          //下一條語(yǔ)句將值 42 賦給局部的 aNumber。aNumber = 42;

          if (false) {

          var aNumber; // 該語(yǔ)句永遠(yuǎn)不會(huì)執(zhí)行。

          aNumber = 123; // 該語(yǔ)句永遠(yuǎn)不會(huì)執(zhí)行。

          } // 條件語(yǔ)句結(jié)束。

          } // 該函數(shù)定義結(jié)束。

          當(dāng) JScript 運(yùn)行函數(shù)時(shí),首先查找所有的變量聲明,

          var someVariable;

          并以未定義的初始值創(chuàng)建變量。如果變量被聲明時(shí)有值,

          var someVariable = "something";

          那么該變量仍以未定義的值初始化,并且只有在運(yùn)行了聲明行時(shí)才被聲明值取代,假如曾經(jīng)被聲明過(guò)。

          JScript 在運(yùn)行代碼前處理變量聲明,所以聲明是位于一個(gè)條件塊中還是其他某些結(jié)構(gòu)中無(wú)關(guān)緊要。JScript 找到所有的變量后立即運(yùn)行函數(shù)中的代碼。如果變量是在函數(shù)中顯式聲明的 ? 也就是說(shuō),如果它出現(xiàn)于賦值表達(dá)式的左邊但沒有用 var 聲明 ? 那么將把它創(chuàng)建為全局變量。

          復(fù)制、傳遞和比較數(shù)據(jù)

          在 JScript 中,對(duì)數(shù)據(jù)的處理取決于該數(shù)據(jù)的類型。

          按值和按引用的比較

          Numbers 和 Boolean 類型的值 (true 和 false) 是按值來(lái)復(fù)制、傳遞和比較的。當(dāng)按值復(fù)制或傳遞時(shí),將在計(jì)算機(jī)內(nèi)存中分配一塊空間并將原值復(fù)制到其中。然后,即使更改原來(lái)的值,也不會(huì)影響所復(fù)制的值(反過(guò)來(lái)也一樣),因?yàn)檫@兩個(gè)值是獨(dú)立的實(shí)體。

          對(duì)象、數(shù)組以及函數(shù)是按引用來(lái)復(fù)制、傳遞和比較的。 當(dāng)按地址復(fù)制或傳遞時(shí),實(shí)際是創(chuàng)建一個(gè)指向原始項(xiàng)的指針,然后就像拷貝一樣來(lái)使用該指針。如果隨后更改原始項(xiàng),則將同時(shí)更改原始項(xiàng)和復(fù)制項(xiàng)(反過(guò)來(lái)也一樣)。實(shí)際上只有一個(gè)實(shí)體;“復(fù)本”并不是一個(gè)真正的復(fù)本,而只是該數(shù)據(jù)的又一個(gè)引用。

          當(dāng)按引用比較時(shí),要想比較成功,兩個(gè)變量必須參照完全相同的實(shí)體。例如,兩個(gè)不同的 Array 對(duì)象即使包含相同的元素也將比較為不相等。要想比較成功,其中一個(gè)變量必須為另一個(gè)的參考。要想檢查兩個(gè)數(shù)組是否包含了相同的元素,比較 toString() 方法的結(jié)果。

          最后,字符串是按引用復(fù)制和傳遞的,但是是按值來(lái)比較的。請(qǐng)注意,假如有兩個(gè) String 對(duì)象(用 new String("something") 創(chuàng)建的),按引用比較它們,但是,如果其中一個(gè)或者兩者都是字符串值的話,按值比較它們。

          注意 鑒于 ASCII和 ANSI 字符集的構(gòu)造方法,按序列順序大寫字母位于小寫字母的前面。例如 "Zoo" 小于 "aardvark"。如果想執(zhí)行不區(qū)分大小寫的匹配,可以對(duì)兩個(gè)字符串調(diào)用 toUpperCase() 或 toLowerCase()。

          傳遞參數(shù)給函數(shù)

          按值傳遞一個(gè)參數(shù)給函數(shù)就是制作該參數(shù)的一個(gè)獨(dú)立復(fù)本,即一個(gè)只存在于該函數(shù)內(nèi)的復(fù)本。即使按引用傳遞對(duì)象和數(shù)組時(shí),如果直接在函數(shù)中用新值覆蓋原先的值,在函數(shù)外并不反映新值。只有在對(duì)象的屬性或者數(shù)組的元素改變時(shí),在函數(shù)外才可以看出。

          例如(使用 IE 對(duì)象模式):

          // 本代碼段破壞(覆蓋)其參數(shù),所以

          // 調(diào)用代碼中反映不出變化。

          function Clobber(param)

          {

          // 破壞參數(shù);在調(diào)用代碼中

          // 看不到。

          param = new Object();

          param.message = "This will not work";

          }

          // 本段代碼改變參數(shù)的屬性,

          // 在調(diào)用代碼中可看到屬性改變。

          function Update(param)

          {

          // 改變對(duì)象的屬性;

          // 可從調(diào)用代碼中看到改變。

          param.message = "I was changed";

          }

          // 創(chuàng)建一個(gè)對(duì)象,并賦給一個(gè)屬性。

          var obj = new Object();

          obj.message = "This is the original";

          // 調(diào)用 Clobber,并輸出 obj.message。注意,它沒有發(fā)生變化。

          Clobber(obj);

          window.alert(obj.message); // 仍然顯示 "This is the original"。

          // 調(diào)用 Update,并輸出 obj.message。注意,它已經(jīng)被改變了。

          Update(obj);

          window.alert(obj.message); // 顯示 "I was changed"。

          檢驗(yàn)數(shù)據(jù)

          當(dāng)按值進(jìn)行檢驗(yàn)時(shí),是比較兩個(gè)截然不同的項(xiàng)以查看它們是否相等。通常,該比較是逐字節(jié)進(jìn)行的。當(dāng)按引用進(jìn)行檢驗(yàn)時(shí),是看這兩項(xiàng)是否是指向同一個(gè)原始項(xiàng)的指針。如果是,則比較結(jié)果是相等;如果不是,即使它們每個(gè)字節(jié)都包含完全一樣的值,比較結(jié)果也為不相等。

          按引用復(fù)制和傳遞字符串能節(jié)約內(nèi)存;但是由于在字符串被創(chuàng)建后不能進(jìn)行更改,因此可以按值進(jìn)行比較。這樣可以檢查兩個(gè)字符串是否包含相同的內(nèi)容,即使它們是完全獨(dú)立產(chǎn)生的。

          posted on 2008-09-02 10:35 deepbluesea 閱讀(175) 評(píng)論(0)  編輯  收藏 所屬分類: JS

          <2008年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          MSN:zzlljj8833@hotmail.com lava:5832911

          常用鏈接

          留言簿(1)

          隨筆分類(9)

          隨筆檔案(18)

          文章分類(1)

          文章檔案(1)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 芜湖县| 巢湖市| 陇川县| 汕尾市| 济阳县| 章丘市| 称多县| 台江县| 尉氏县| 长武县| 隆林| 临湘市| 安丘市| 开远市| 东乡族自治县| 商丘市| 余干县| 安国市| 竹北市| 绥滨县| 苏尼特右旗| 宁津县| 栖霞市| 海原县| 寻乌县| 正定县| 城口县| 奉新县| 旬邑县| 巴林右旗| 湟中县| 沁源县| 泸溪县| 武安市| 长葛市| 广州市| 浦北县| 黄平县| 扶风县| 彰化市| 从江县|