久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

跨越邊界: JavaScript 語言特性

 [email protected] 2007-03-12

2007 年 1 月 18 日

JavaScript 常被人們認(rèn)為是編程語言中無足輕重的一員。這種觀點的形成可以“歸功”于其開發(fā)工具,、復(fù)雜且不一致的面向 HTML 頁面的文檔對象模型以及不一致的瀏覽器實現(xiàn),。但 JavaScript 絕對不僅僅是一個玩具這么簡單。在本文中,,Bruce Tate 向您介紹了 JavaScript 的語言特性,。

幾乎每個 Web 開發(fā)人員都曾有過詛咒 JavaScript 的經(jīng)歷,。這個備受爭議的語言受累于其復(fù)雜的稱為文檔對象模型 (DOM)的編程模型,、糟糕的實現(xiàn)和調(diào)試工具以及不一致的瀏覽器實現(xiàn),。直到最近,很多開發(fā)人員還認(rèn)為 Javascript 從最好的方面說是無可避免之災(zāi)禍,,從最壞的方面說不過是一種玩具罷了,。

然而 JavaScript 現(xiàn)在開始日益重要起來,而且成為了廣泛應(yīng)用于 Web 開發(fā)的腳本語言,。JavaScript 的復(fù)蘇使一些業(yè)界領(lǐng)袖人物也不得不開始重新審視這種編程語言,。諸如 Ajax (Asynchronous JavaScript + XML) 這樣的編程技術(shù)讓 Web 網(wǎng)頁更加迷人。而完整的 Web 開發(fā)框架,,比如 Apache Cocoon,,則讓 JavaScript 的應(yīng)用越來越多,使其不只限于是一種用于制作 Web 頁面的簡單腳本,。JavaScript 的一種稱為 ActionScript 的派生物也推動了 Macromedia 的 Flash 客戶端框架的發(fā)展,。運行在 JVM 上的實現(xiàn) Rhino 讓 JavaScript 成為了 Java? 開發(fā)人員所首選的一類腳本語言(參見 參考資料)。

我的好友兼同事 Stuart Halloway 是 Ajax 方面的專家,,曾在其教授的 JavaScript 課程中做過這樣的開場白:“到 2011 年,,JavaScript 將被公認(rèn)為是一種擁有開發(fā)現(xiàn)代應(yīng)用程序所需的一整套新特性的語言” 。他繼而介紹說 JavaScript 程序要比類似的 Java 程序緊密十倍,,并繼續(xù)展示了使其之所以如此的一些語言特性,。

關(guān)于這個系列

跨越邊界系列中,作者 Bruce Tate 提出了這樣一個主張:今天的 Java 程序員通過學(xué)習(xí)其他技術(shù)和語言,,會得到很好的幫助,。編程領(lǐng)域已經(jīng)發(fā)生了變化,Java 技術(shù)不再是所有開發(fā)項目理所當(dāng)然的最佳選擇,。其他框架正在影響 Java 框架構(gòu)建的方式,,而從其他語言學(xué)到的概念也有助于 Java 編程。對 Python(或 Ruby,、Smalltalk 等等)代碼的編寫可能改變 Java 編碼的方式,。

這個系列介紹的編程概念和技術(shù),與 Java 開發(fā)有根本的不同,,但可以直接應(yīng)用于 Java 編程,。在某些情況下,需要集成這些技術(shù)來利用它們,。在其他情況下,,可以直接應(yīng)用這些概念。單獨的工具并不重要,,重要的是其他語言和框架可以影響 Java 社區(qū)中的開發(fā)人員,、框架,甚至是基本方式。

在這篇文章中,,我將帶您探究 JavaScript 的一些特性,,看看這些特性如何讓它如此具有吸引力:

  • 高階函數(shù): 一個高階函數(shù)可以將函數(shù)作為參數(shù),也可以返回一個函數(shù),。此特性讓 JavaScript 程序員可以用 Java 語言所不能提供的方法來操縱函數(shù),。

  • 動態(tài)類型:通過延遲綁定,JavaScript 可以更準(zhǔn)確和更靈活,。

  • 靈活的對象模型:JavaScript 的對象模型使用一種相對不常見的方式進行繼承 —— 稱為原型 —— 而不是 Java 語言中更常見的基于類的對象模型,。

您可能已經(jīng)熟悉動態(tài)類型模型、高階函數(shù)形式的函數(shù)式編程以及開放對象模型這些概念,,因為我在其他的跨越邊界 系列文章中已經(jīng)作過相關(guān)的介紹,。如果您從未進行過任何正式的 JavaScript 開發(fā),您很可能會認(rèn)為這些特性屬于非常復(fù)雜的語言,,例如 Python,、Lisp、Smalltalk 和 Haskell,,而絕非像 JavaScript 這樣的語言所能提供的,。因此,我將用實際的代碼示例來說明這些概念,。

立即開始

您無需設(shè)置 JavaScript,。如果您可以在瀏覽器中閱讀此篇文章,就證明您已經(jīng)準(zhǔn)備就緒了,。本文包含的所有編程示例都可以在大多數(shù)瀏覽器內(nèi)運行,。我使用的是 Firefox。

用在 <script type=‘text/javascript‘></script> 標(biāo)記之間所包含的 JavaScript 加載簡單的 Web 頁面,。清單 1 可以顯示 Hello, World 文本:



清單 1. Hello, world
                        <script type=‘text/javascript‘>
                        alert(‘Hello, World.‘)
                        </script>
                        

要運行此代碼,,只需創(chuàng)建一個名為 example1.html 的文件。將清單 1 的代碼復(fù)制到該文件內(nèi),,并在瀏覽器中加載此文件(參看 下載 部分以獲得本文使用的所有示例 HTML 文件),。注意到每次重載此頁面時,該代碼都會立即執(zhí)行,。

alert 是個函數(shù)調(diào)用,,只有一個字符串作為參數(shù)。圖 1 顯示了由清單 1 中的代碼彈出的警告框,,顯示文本 “Hello, World”,。如果代碼在 HTML body 之內(nèi)(目前并未指定任何 body,但瀏覽器能接受不規(guī)則的 HTML,,并且整個頁面都默然作為一個 body 被處理),。頁面一旦加載,,JavaScript 就會立即執(zhí)行。



圖 1. Hello, world
Hello, World.

如果要延遲執(zhí)行,,可以在 HTML <head> 元素聲明 JavaScript 函數(shù),,如清單 2 所示:



清單 2. 延遲執(zhí)行
                        <head>
                        <script type=‘text/javascript‘>
                        function hello() {
                        alert(‘Hello, World.‘)
                        }
                        </script>
                        </head>
                        <body>
                        <button onclick="hello();">Say Hello</button>
                        </body>
                        

將清單 2 中的代碼輸入到一個 HTML 文件,在瀏覽器內(nèi)加載該文件,,單擊 Say Hello 按鈕,,結(jié)果如圖 2 所示:



圖 2. 延遲執(zhí)行
延遲執(zhí)行




回頁首


高階函數(shù)

清單 2,,可以大致體會到一些 JavaScript 在操縱函數(shù)方面的能力,。將函數(shù)名稱傳遞給 HTML button 標(biāo)記并利用 HTML 的內(nèi)置事件模型。使用 JavaScript 時,,我會經(jīng)常在變量或數(shù)組中存儲函數(shù)(在本文后面的 對象模型 一節(jié),,您會看到 JavaScript 對象模型策略大量使用了此技巧)。例如,,查看一下清單 3:



清單 3. 用變量操縱函數(shù)
                        <head>
                        <script type=‘text/javascript‘>
                        hot = function hot() {
                        alert(‘Sweat.‘)
                        }
                        cold  = function cold() {
                        alert(‘Shiver.‘)
                        }
                        function swap() {
                        temp = hot
                        hot = cold
                        cold = temp
                        alert(‘Swapped.‘)
                        }
                        </script>
                        </head>
                        <body>
                        <button onclick="hot();">Hot</button>
                        <button onclick="cold();">Cold</button>
                        <button onclick="swap();">Swap</button>
                        </body>
                        

函數(shù)是 JavaScript 中的一類對象,,可以自由地操縱它們。首先我聲明兩個函數(shù):hotcold,。并分別在不同的變量存儲它們,。單擊 Hot 或 Cold 按鈕會調(diào)用對應(yīng)的函數(shù),生成一個告警,。接下來,,聲明另一個函數(shù)用來交換 Hot 和 Cold 按鈕的值,將此函數(shù)與第三個按鈕關(guān)聯(lián),,該按鈕顯示如圖 3 所示的告警:



圖 3. 操縱函數(shù)

這個例子說明可以像處理其他變量一樣處理函數(shù),。C 開發(fā)人員很容易將此概念看作是函數(shù)指針 功能,但 JavaScript 的高階函數(shù)的功能更為強大,。該特性讓 JavaScript 程序員能夠像處理其他變量類型一樣輕松處理動作或函數(shù),。

將函數(shù)用作函數(shù)的參數(shù),或?qū)⒑瘮?shù)作為值返回,,這些概念屬于高階函數(shù)的領(lǐng)域,。清單 4 對 清單 3 做了一點點修改,顯示了能返回函數(shù)的高階函數(shù):



清單 4. 高階函數(shù)
                        <head>
                        <script type=‘text/javascript‘>
                        function temperature() {
                        return current
                        }
                        hot = function hot() {
                        alert(‘Hot.‘)
                        }
                        cold  = function cold() {
                        alert(‘Cold.‘)
                        }
                        current = hot
                        function swap() {
                        if(current == hot) {
                        current = cold
                        } else {
                        current = hot
                        }
                        }
                        </script>
                        </head>
                        <body>
                        <button onclick="funct = temperature()();">Temperature</button>
                        <button onclick="swap();">Swap</button>
                        </body>
                        

這個例子解決了一個常見問題:如何將更改中的行為附加到用戶接口事件,?通過高階函數(shù),,這很容易做到。temperature 高階函數(shù)返回 current 的值,,而 current 又可以有 hotcold 函數(shù),。看一下這個有些陳舊的函數(shù)調(diào)用:temperature()(),。第一組括號用于調(diào)用 temperature 函數(shù),。第二組括號調(diào)用由 temperature 返回 的函數(shù),。圖 4 顯示了輸出:



圖 4. 高階函數(shù)
高階函數(shù)

高階函數(shù)是函數(shù)式編程的基礎(chǔ),對比面向?qū)ο缶幊?,函?shù)式編程代表了更高級別的抽象,。但 JavaScript 的實力并不僅限于高階函數(shù)。JavaScript 的動態(tài)類型就極為適合 UI 開發(fā),。





回頁首


動態(tài)類型

通過靜態(tài)類型,,編譯器可以檢查參數(shù)和變量的值或針對一個給定操作所允許的返回值。其優(yōu)勢是編譯器可以做額外的錯誤檢查,。而且靜態(tài)類型還可以為諸如 IDE 這樣的工具提供更多信息,,帶來其他一些特性,比如更好的代碼完成功能,。但靜態(tài)類型也存在著如下一些劣勢:

  • 必須提前聲明意圖,,這常常會導(dǎo)致靈活性降低。例如,,更改一個 Java 類就會更改類的類型,,因而必須重新編譯。對比之下,,Ruby 允許開放的類,,但更改一個 Java 類還是會更改類的類型。

  • 要實現(xiàn)相同的功能,,必須輸入更多的代碼,。例如,必須用參數(shù)形式包括進類型信息,,必須用函數(shù)形式返回值和所有變量的類型,。另外,還必須聲明所有變量并顯式地轉(zhuǎn)化類型,。

  • 靜態(tài)語言的編譯-部署周期要比動態(tài)語言的部署周期長,,盡管一些工具可被用來在某種程度上緩解這一問題。

靜態(tài)類型更適合用于構(gòu)建中間件或操作系統(tǒng)的語言中,。UI 開發(fā)常常需要更高的效率和靈活性,,所以更適合采用動態(tài)類型。我深知這種做法存在危險,。相信使用過 JavaScript 的 Web 開發(fā)人員都曾經(jīng)為編譯器本應(yīng)檢測到的錯誤類型的變量而絞盡腦汁,。但它所帶來的優(yōu)勢同樣不可否認(rèn)。下面將舉例加以說明,。

首先,,考慮一個對象的情況。在清單 5 中,,創(chuàng)建一個新對象,,并訪問一個不存在的屬性,,名為 color



清單 5. 引入一個屬性
                        <script type=‘text/javascript‘>
                        blank_object = new Object();
                        blank_object.color = ‘blue‘
                        alert(‘The color is ‘ + blank_object.color)
                        </script>
                        

當(dāng)加載并執(zhí)行此應(yīng)用程序時,會得到如圖 5 所示的結(jié)果:



圖 5. 引入屬性
 引入屬性

JavaScript 并不會報告 blue 屬性不存在的錯誤,。靜態(tài)類型的擁護者大都會被本例所嚇倒,,因為本例中的錯誤被很好地隱匿了。雖然這種做法多少會讓您感覺有些不正當(dāng),,但您也不能否認(rèn)它巨大的誘惑力,。您可以很快引入屬性。如果將本例和本文之前的例子結(jié)合起來,,還可以引入行為,。記住,變量可以保存函數(shù),!所以,,基于動態(tài)類型和高階函數(shù),您可以在任何時候向類中引入任意的行為,。

可以輕松地重寫 清單 5,使其如清單 6 所示:



清單 6. 引入行為
                        <script type=‘text/javascript‘>
                        blank_object = new Object();
                        blank_object.color = function() { return ‘blue‘}
                        alert(‘The color is ‘ + blank_object.color())
                        </script>
                        

從上例可以看出,,在 JavaScript 的不同概念之間可以如此輕松地來回變換,,其含義上的變化很大 —— 比如,是引入行為還是引入數(shù)據(jù) —— 但語法上的變化卻很小,。該語言很好的延展性是它的一種優(yōu)勢,,但同樣也是其缺點所在。實際上,,該語言本身的對象模型就是 JavaScript 延展程度的一種體現(xiàn),。





回頁首


對象模型

到目前為止,您應(yīng)該對 JavaScript 有一個正確的評價了,,它絕非只如一個玩具那么簡單,。事實上,很多人都使用過其對象模型創(chuàng)建過極為復(fù)雜,、設(shè)計良好的面向?qū)ο筌浖?。但對象模型尤其是用于繼承的對象模型又非您一貫認(rèn)為的那樣。

Java 語言是基于類的,。當(dāng)構(gòu)建應(yīng)用程序時,,也同時構(gòu)建了可以作為所有對象的模板的新類。然后調(diào)用 new 來實例化該模板,,創(chuàng)建一個新對象,。而在 JavaScript 中,所創(chuàng)建的是一個原型,,此原型是一個實例,,可以創(chuàng)建所有未來的對象,。

現(xiàn)在先暫且放下這些抽象的概念,去查看一些實際代碼,。比如,,清單 7 創(chuàng)建了一個簡單的 Animal,它具有 name 屬性和 speak 動作,。其他動物會從這個基礎(chǔ)繼承,。



清單 7. 創(chuàng)建一個構(gòu)造函數(shù)
                        <script type=‘text/javascript‘>
                        Animal = function() {
                        this.name = "nobody"
                        this.speak = function () {
                        return "Who am I?"
                        }
                        }
                        myAnimal = new Animal();
                        alert(‘The animal named ‘ + myAnimal.name +
                        ‘ says ‘ + myAnimal.speak());
                        </script>
                        

清單 7 的結(jié)果如圖 6 所示:



圖 6. 創(chuàng)建一個構(gòu)造函數(shù)
構(gòu)造函數(shù)

對于 Java 開發(fā)人員而言,清單 7 中的代碼看起來多少有點生疏和奇怪,。實際上對于沒有親自構(gòu)建過對象的許多 JavaScript 開發(fā)人員來說,,這些代碼同樣看起來有點生疏和奇怪。也許,,下面的解釋可以讓大家能夠更好地理解這段代碼,。

實際上,您只需重點關(guān)注其中三段信息,。首先,,JavaScript 用嵌套函數(shù)表示對象。這意味著清單 7 中的 Animal 的定義是一種有效的語法,。第二,,JavaScript 基于原型或現(xiàn)有的對象的實例來構(gòu)造對象,而非基于類模板,。funct() 是一種調(diào)用,,但 new Animal() 卻基于 Animal 內(nèi)的原型構(gòu)造一個對象。最后,,在 JavaScript 中,,對象只是函數(shù)和變量的集合。每個對象并不與類型相關(guān),,所以可以自由地修改這種結(jié)構(gòu),。

回到 清單 7。如您所見,,JavaScript 基于在 Animal 中指定的原型定義一個新對象:myAnimal,。繼而可以使用原型中的屬性和函數(shù),甚或重定義函數(shù)和屬性,。這種靈活性可能會讓 Java 開發(fā)人員受不了,,因為他們不習(xí)慣這種行為,但它的確是一種十分強大的模型,。

現(xiàn)在我還要更深入一步,。您還可以使用名為 prototype 實例變量來指定對象的基礎(chǔ)。方法是設(shè)置 prototype 實例變量使其指向繼承鏈的父,。如此設(shè)置 prototype 之后,,您所創(chuàng)建的對象會為未指定的那些對象繼承屬性和函數(shù),。這樣一來,您就可以模仿面向?qū)ο蟮睦^承概念,。以清單 8 為例:



清單 8. 通過原型繼承
                        <script type=‘text/javascript‘>
                        Animal = function() {
                        this.name = "nobody"
                        this.speak = function () {
                        return "Who am I?"
                        }
                        }
                        Dog = function() {
                        this.speak = function() {
                        return "Woof!"
                        }
                        }
                        Dog.prototype = new Animal();
                        myAnimal = new Dog();
                        alert(‘The animal named ‘ + myAnimal.name +
                        ‘ says ‘ + myAnimal.speak());
                        </script>
                        

在清單 8 中,,創(chuàng)建了一個 Dog 原型。此原型基于 Animal,。Dog 重定義 speak() 方法但卻不會對 name() 方法做任何改動,。隨后,將原型 Dog 設(shè)置成 Animal,。圖 7 顯示了其結(jié)果:



圖 7. 通過原型繼承
繼承

這也展示了 JavaScript 是如何解決到屬性或方法的引用問題的:

  • JavaScript 基于原始的原型創(chuàng)建實例,,該原型在構(gòu)造函數(shù)中定義。任何對方法或?qū)傩缘囊枚紩褂盟傻脑几北尽?br>
  • 您可以在對象內(nèi)像定義其他任何變量一樣重新定義這些變量,。這樣做必然會更改此對象,。所以您顯式定義的任何屬性或函數(shù)都將比在原始的原型中定義的那些屬性或函數(shù)優(yōu)先級要高。

  • 如果您顯式設(shè)置了名為 prototype 的實例變量,,JavaScript 就會在此實例中尋找任何未定義的實例變量或?qū)傩?。這種查找是遞歸的:如果 在 prototype 內(nèi)定義的實例不能找到屬性或函數(shù),它就會在 原型中查找,,依此類推,。

那么,JavaScript 的繼承模型到底是什么樣的,?這取決于您如何對它進行定義。您需要定義繼承行為以便可以覆蓋它,。然而,,從本質(zhì)上講,JavaScript 更像是一種函數(shù)式語言,,而非面向?qū)ο蟮恼Z言,,它使用一些智能的語法和語義來仿真高度復(fù)雜的行為。其對象模型極為靈活,、開放和強大,,具有全部的反射性。有些人可能會說它太過靈活,。而我的忠告則是,,按具體作業(yè)的需要選擇合適的工具。





回頁首


結(jié)束語

JavaScript 對象模型構(gòu)建在該語言的其他功能之上來支持大量的庫,,比如 Dojo(參見 參考資料),。這種靈活性讓每個框架能夠以一種精細(xì)的方式更改對象模型。在某種程度上,,這種靈活性是一種極大的缺點,。它可以導(dǎo)致可怕的互操作性問題(盡管該語言的靈活性可以部分緩解這些問題),。

而另一方面,靈活性又是一種巨大的優(yōu)勢,。Java 語言一直苦于無法充分增強其靈活性,,原因是它的基本對象模型還未靈活到可以被擴展的程度。一個典型的企業(yè)級開發(fā)人員為能夠成功使用 Java 語言必須要學(xué)習(xí)很多東西,,而新出現(xiàn)的一些優(yōu)秀的開放源碼項目和新技術(shù),,比如面向方面編程、Spring 編程框架和字節(jié)碼增強庫,,則帶來了大量要學(xué)的代碼,。

最后,JavaScript 優(yōu)秀的靈活性的確讓您體會到了一些高階語言的強大功能,。當(dāng)然您無需選擇為每個項目或大多數(shù)項目都做這樣的權(quán)衡和折衷,。但了解一種語言的優(yōu)勢和劣勢 —— 通過參考大量信息,而不僅僅基于廣告宣傳或公眾意見 —— 會讓您可以更好地控制何時需要使用以及何時不能使用這種語言,。當(dāng)您在修改 JavaScript Web 小部件時,,您至少知道該如何讓此語言發(fā)揮它最大的優(yōu)勢。請繼續(xù)跨越邊界吧,。






回頁首


下載

描述 名字 大小 下載方法
本文的示例 HTML 文件 j-cb12196.zip 3KB HTTP
關(guān)于下載方法的信息 Get Adobe? Reader?


參考資料

學(xué)習(xí)

討論


關(guān)于作者

Bruce Tate 是位父親,、山地車手,、皮艇手,住在德克薩斯州的奧斯汀,。他是三本最暢銷 Java 圖書的作者,,包括獲得 Jolt 獎的 Better, Faster, Lighter Java。他最近推出了 From Java to RubyRails: Up and Running,。他在 IBM 工作了 13 年,,而后創(chuàng)立了 RapidRed 顧問公司,在那里他專攻基于 Ruby 的輕量級開發(fā)策略和體系結(jié)構(gòu)及 Ruby on Rails 框架?,F(xiàn)在他是 WellGood LLC 的 CTO ,,該公司致力于為非盈利組織和福利機構(gòu)開辟市場。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多