




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、Json prototype 閉包 構造函數(shù)Json,prototype,閉包,構造函數(shù)2010-07-08 19:53Json,prototype,閉包,構造函數(shù)2008年10月24日星期五上午11:34JSON已經(jīng)說了許多了許多話題了,但有一個很基本的問題我們忘了討論,那就是:怎樣建立對象?在前面的示例中,我們已經(jīng)涉及到了對象的建立了。我們使用了一種被稱為JavaScript Object Notation(縮寫JSON)的形式,翻譯為中文就是JavaScript對象表示法。JSON為創(chuàng)建對象提供了非常簡單的方法。例如,創(chuàng)建一個沒有任何屬性的對象:var o=;創(chuàng)建一個對象并設置屬性及初始
2、值:var person=name:Angel,age:18,married:false;創(chuàng)建一個對象并設置屬性和方法:var speaker=text:Hello World,say:function()alert(this.text);創(chuàng)建一個更復雜的對象,嵌套其他對象和對象數(shù)組等:var company=name:Microsoft,product:softwares,chairman:name:Bill Gates,age:53,Married:true,employees:name:Angel,age:26,Married:false,name:Hanson,age:32,Marre
3、d:true,readme:function()document.write(+product+duct);JSON的形式就是用大括號包括起來的項目列表,每一個項目間并用逗號,分隔,而項目就是用冒號:分隔的屬性名和屬性值。這是典型的字典表示形式,也再次表明了JavaScript里的對象就是字典結構。不管多么復雜的對象,都可以被一句JSON代碼來創(chuàng)建并賦值。其實,JSON就是JavaScript對象最好的序列化形式,它比XML更簡潔也更省空間。對象可以作為一個JSON形式的字符串,在網(wǎng)絡間自由傳遞和交換信息。而當需要將這個JSON字符串變成一個JavaScrip
4、t對象時,只需要使用eval函數(shù)這個強大的數(shù)碼轉換引擎,就立即能得到一個JavaScript內存對象。正是由于JSON的這種簡單樸素的天生麗質,才使得她在AJAX舞臺上成為璀璨奪目的明星。JavaScript就是這樣,把面向對象那些看似復雜的東西,用及其簡潔的形式表達出來。卸下對象浮華的濃妝,還對象一個眉目清晰!構造對象好了,接下我們來討論一下對象的另一種創(chuàng)建方法。除JSON外,在JavaScript中我們可以使用new操作符結合一個函數(shù)的形式來創(chuàng)建對象。例如:function MyFunc();/定義一個空函數(shù)var anObj=new MyFunc();/使用new操作符,借助MyFun函
5、數(shù),就創(chuàng)建了一個對象JavaScript的這種創(chuàng)建對象的方式可真有意思,如何去理解這種寫法呢?其實,可以把上面的代碼改寫成這種等價形式:function MyFunc();var anObj=;/創(chuàng)建一個對象MyFunc.call(anObj);/將anObj對象作為this指針調用MyFunc函數(shù)我們就可以這樣理解,JavaScript先用new操作符創(chuàng)建了一個對象,緊接著就將這個對象作為this參數(shù)調用了后面的函數(shù)。其實,JavaScript內部就是這么做的,而且任何函數(shù)都可以被這樣調用!但從anObj=new MyFunc()這種形式,我們又看到一個熟悉的身影,C+和C#不就是這樣創(chuàng)建對
6、象的嗎?原來,條條大路通靈山,殊途同歸??!請看下面的代碼:1 function Person(name)/帶參數(shù)的構造函數(shù)23 =name;/將參數(shù)值賦給給this對象的屬性4 this.SayHello=function()alert(Hello,Im+);/給this對象定義一個SayHello方法。5;6 7function Employee(name,salary)/子構造函數(shù)89 Person.call(this,name);/將this傳給父構造函數(shù)10 this.salary=salary;/設置一個this的salary屬性11 this.S
7、howMeTheMoney=function()alert(+$+this.salary);/添加ShowMeTheMoney方法。12;13 14 var BillGates=new Person(Bill Gates);/用Person構造函數(shù)創(chuàng)建BillGates對象15 var SteveJobs=new Employee(Steve Jobs,1234);/用Empolyee構造函數(shù)創(chuàng)建SteveJobs對象16 17 BillGates.SayHello();/顯示:Im Bill Gates 18 SteveJobs.SayHello();/顯示:Im Stev
8、e Jobs 19 SteveJobs.ShowMeTheMoney();/顯示:Steve Jobs34 20 21 alert(BillGates.constructor=Person);/顯示:true 22 alert(SteveJobs.constructor=Employee);/顯示:true 23 24 alert(BillGates.SayHello=SteveJobs.SayHello);/顯示:false這段代碼表明,函數(shù)不但可以當作構造函數(shù),而且還可以帶參數(shù),還可以為對象添加成員和方法。其中的第9行,Employee構造函數(shù)又將自己接收的this作為參數(shù)調用Person
9、構造函數(shù),這就是相當于調用基類的構造函數(shù)。第21、22行還表明這樣一個意思:BillGates是由Person構造的,而SteveJobs是由Employee構造的。對象內置的constructor屬性還指明了構造對象所用的具體函數(shù)!其實,如果你愿意把函數(shù)當作類的話,她就是類,因為她本來就有類的那些特征。難道不是嗎?她生出的兒子各個都有相同的特征,而且構造函數(shù)也與類同名嘛!但要注意的是,用構造函數(shù)操作this對象創(chuàng)建出來的每一個對象,不但具有各自的成員數(shù)據(jù),而且還具有各自的方法數(shù)據(jù)。換句話說,方法的代碼體(體現(xiàn)函數(shù)邏輯的數(shù)據(jù))在每一個對象中都存在一個副本。盡管每一個代碼副本的邏輯是相同的,但對
10、象們確實是各自保存了一份代碼體。上例中的最后一句說明了這一實事,這也解釋了JavaScript中的函數(shù)就是對象的概念。同一類的對象各自有一份方法代碼顯然是一種浪費。在傳統(tǒng)的對象語言中,方法函數(shù)并不象JavaScript那樣是個對象概念。即使也有象函數(shù)指針、方法指針或委托那樣的變化形式,但其實質也是對同一份代碼的引用。一般的對象語言很難遇到這種情況。不過,JavaScript語言有大的靈活性。我們可以先定義一份唯一的方法函數(shù)體,并在構造this對象時使用這唯一的函數(shù)對象作為其方法,就能共享方法邏輯。例如:function SayHello()/先定義一份SayHello函數(shù)代碼alert(Hel
11、lo,Im+);function Person(name)/帶參數(shù)的構造函數(shù)=name;/將參數(shù)值賦給給this對象的屬性this.SayHello=SayHello;/給this對象SayHello方法賦值為前面那份SayHello代碼。;var BillGates=new Person(Bill Gates);/創(chuàng)建BillGates對象var SteveJobs=new Person(Steve Jobs);/創(chuàng)建SteveJobs對象alert(BillGates.SayHello=SteveJobs.SayHello);/顯示:true其中,最后一
12、行的輸出結果表明兩個對象確實共享了一個函數(shù)對象。雖然,這段程序達到了共享了一份方法代碼的目的,但卻不怎么優(yōu)雅。因為,定義SayHello方法時反映不出其與Person類的關系。優(yōu)雅這個詞用來形容代碼,也不知道是誰先提出來的。不過,這個詞反映了程序員已經(jīng)從追求代碼的正確、高效、可靠和易讀等基礎上,向著追求代碼的美觀感覺和藝術境界的層次發(fā)展,程序人生又多了些浪漫色彩。顯然,JavaScript早想到了這一問題,她的設計者們?yōu)榇颂峁┝艘粋€有趣的prototype概念。初看原型prototype源自法語,軟件界的標準翻譯為原型,代表事物的初始形態(tài),也含有模型和樣板的意義。JavaScript中的pro
13、totype概念恰如其分地反映了這個詞的內含,我們不能將其理解為C+的prototype那種預先聲明的概念。JavaScript的所有function類型的對象都有一個prototype屬性。這個prototype屬性本身又是一個object類型的對象,因此我們也可以給這個prototype對象添加任意的屬性和方法。既然prototype是對象的原型,那么由該函數(shù)構造出來的對象應該都會具有這個原型的特性。事實上,在構造函數(shù)的prototype上定義的所有屬性和方法,都是可以通過其構造的對象直接訪問和調用的。也可以這么說,prototype提供了一群同類對象共享屬性和方法的機制。我們先來看看下面
14、的代碼:function Person(name)=name;/設置對象屬性,每個對象各自一份屬性數(shù)據(jù);Ptotype.SayHello=function()/給Person函數(shù)的prototype添加SayHello方法。alert(Hello,Im+);var BillGates=new Person(Bill Gates);/創(chuàng)建BillGates對象var SteveJobs=new Person(Steve Jobs);/創(chuàng)建SteveJobs對象BillGates.SayHello();/通過BillGates對象直接調用到Sa
15、yHello方法SteveJobs.SayHello();/通過SteveJobs對象直接調用到SayHello方法alert(BillGates.SayHello=SteveJobs.SayHello);/因為兩個對象是共享prototype的SayHello,所以顯示:true程序運行的結果表明,構造函數(shù)的prototype上定義的方法確實可以通過對象直接調用到,而且代碼是共享的。顯然,把方法設置到prototype的寫法顯得優(yōu)雅多了,盡管調用形式?jīng)]有變,但邏輯上卻體現(xiàn)了方法與類的關系,相對前面的寫法,更容易理解和組織代碼。那么,對于多層次類型的構造函數(shù)情況又如何呢?然而,比靜態(tài)對象語言更
16、神奇的是,我們可以隨時給原型對象動態(tài)添加新的屬性和方法,從而動態(tài)地擴展基類的功能特性。這在靜態(tài)對象語言中是很難想象的。我們來看下面的代碼:以下是引用片段:function Person(name)=name;Ptotype.SayHello=function()/建立對象前定義的方法alert(Hello,Im+);var BillGates=new Person(Bill Gates);/建立對象BillGates.SayHello();Ptotype.Retire=function()/建立對象后再動態(tài)擴展原型的方法a
17、lert(Poor++,bye bye!);BillGates.Retire();/動態(tài)擴展的方法即可被先前建立的對象立即調用阿彌佗佛,原型繼承竟然可以玩出有這樣的法術!原型擴展想必君的悟性極高,可能你會這樣想:如果在JavaScript內置的那些如Object和Function等函數(shù)的prototype上添加些新的方法和屬性,是不是就能擴展JavaScript的功能呢?那么,恭喜你,你得到了!在AJAX技術迅猛發(fā)展的今天,許多成功的AJAX項目的JavaScript運行庫都大量擴展了內置函數(shù)的prototype功能。比如微軟的ASP.NET AJAX,就給這些內置函數(shù)及其p
18、rototype添加了大量的新特性,從而增強了JavaScript的功能。我們來看一段摘自MicrosoftAjax.debug.js中的代碼:Stotype.trim=function String$trim()if(arguments.length!=0)throw Error.parameterCount();return this.replace(/s+|s+$/g,);這段代碼就是給內置String函數(shù)的prototype擴展了一個trim方法,于是所有的String類對象都有了trim方法了。有了這個擴展,今后要去除字符串兩段的空白,就不用再分別處理了,因為任何字
19、符串都有了這個擴展功能,只要調用即可,真的很方便。當然,幾乎很少有人去給Object的prototype添加方法,因為那會影響到所有的對象,除非在你的架構中這種方法的確是所有對象都需要的。前兩年,微軟在設計AJAX類庫的初期,用了一種被稱為閉包(closure)的技術來模擬類。其大致模型如下:以下是引用片段:function Person(firstName,lastName,age)/私有變量:var _firstName=firstName;var _lastName=lastName;/公共變量:this.age=age;/方法:this.getName=function()return
20、(firstName+lastName);this.SayHello=function()alert(Hello,Im+firstName+lastName);var BillGates=new Person(Bill,Gates,53);var SteveJobs=new Person(Steve,Jobs,53);BillGates.SayHello();SteveJobs.SayHello();alert(BillGates.getName()+BillGates.age);alert(BillGates.firstName);/這里不能訪問到私有變量很顯然,這種模型的類描述特別象C#語
21、言的描述形式,在一個構造函數(shù)里依次定義了私有成員、公共屬性和可用的方法,顯得非常優(yōu)雅嘛。特別是閉包機制可以模擬對私有成員的保護機制,做得非常漂亮。所謂的閉包,就是在構造函數(shù)體內定義另外的函數(shù)作為目標對象的方法函數(shù),而這個對象的方法函數(shù)反過來引用外層外層函數(shù)體中的臨時變量。這使得只要目標對象在生存期內始終能保持其方法,就能間接保持原構造函數(shù)體當時用到的臨時變量值。盡管最開始的構造函數(shù)調用已經(jīng)結束,臨時變量的名稱也都消失了,但在目標對象的方法內卻始終能引用到該變量的值,而且該值只能通這種方法來訪問。即使再次調用相同的構造函數(shù),但只會生成新對象和方法,新的臨時變量只是對應新的值,和上次那次調用的是各
22、自獨立的。的確很巧妙!但是前面我們說過,給每一個對象設置一份方法是一種很大的浪費。還有,閉包這種間接保持變量值的機制,往往會給JavaSript的垃圾回收器制造難題。特別是遇到對象間復雜的循環(huán)引用時,垃圾回收的判斷邏輯非常復雜。無獨有偶,IE瀏覽器早期版本確實存在JavaSript垃圾回收方面的內存泄漏問題。再加上閉包模型在性能測試方面的表現(xiàn)不佳,微軟最終放棄了閉包模型,而改用原型模型。正所謂有得必有失嘛。原型模型需要一個構造函數(shù)來定義對象的成員,而方法卻依附在該構造函數(shù)的原型上。大致寫法如下:/定義構造函數(shù)function Person(name)=name;/在構造函數(shù)中
23、定義成員;/方法定義到構造函數(shù)的prototype上Ptotype.SayHello=function()alert(Hello,Im+);/子類構造函數(shù)function Employee(name,salary)Person.call(this,name);/調用上層構造函數(shù)this.salary=salary;/擴展的成員;/子類構造函數(shù)首先需要用上層構造函數(shù)來建立prototype對象,實現(xiàn)繼承的概念Etotype=new Person()/只需要其prototype的方法,此對象的成員沒有任何意義!/子類方法也定義到構造函數(shù)之上
24、Etotype.ShowMeTheMoney=function()alert(+$+this.salary);var BillGates=new Person(Bill Gates);BillGates.SayHello();var SteveJobs=new Employee(Steve Jobs,1234);SteveJobs.SayHello();SteveJobs.ShowMeTheMoney();原型類模型雖然不能模擬真正的私有變量,而且也要分兩部分來定義類,顯得不怎么優(yōu)雅。不過,對象間的方法是共享的,不會遇到垃圾回收問題,而且性能優(yōu)于閉包模型
25、。正所謂有失必有得嘛。在原型模型中,為了實現(xiàn)類繼承,必須首先將子類構造函數(shù)的prototype設置為一個父類的對象實例。創(chuàng)建這個父類對象實例的目的就是為了構成原型鏈,以起到共享上層原型方法作用。但創(chuàng)建這個實例對象時,上層構造函數(shù)也會給它設置對象成員,這些對象成員對于繼承來說是沒有意義的。雖然,我們也沒有給構造函數(shù)傳遞參數(shù),但確實創(chuàng)建了若干沒有用的成員,盡管其值是undefined,這也是一種浪費啊。唉!世界上沒有完美的事情?。∧敲?,我們能否自己定義一個對象來當作原型,并在這個原型上描述類,然后將這個原型設置給新創(chuàng)建的對象,將其當作對象的類呢?我們又能否將這個原型中的一個方法當作構造函數(shù),去初始
26、化新建的對象呢?例如,我們定義這樣一個原型對象:var Person=/定義一個對象來作為原型類Create:function(name,age)/這個當構造函數(shù)=name;this.age=age;,SayHello:function()/定義方法alert(Hello,Im+);,HowOld:function()/定義方法alert(+is+this.age+years old.);這個JSON形式的寫法多么象一個C#的類啊!既有構造函數(shù),又有各種方法。如果可以用某種形式來創(chuàng)建對象,并將對象的內置的原型設置為上面這個類對象,不就相當于
27、創(chuàng)建該類的對象了嗎?但遺憾的是,我們幾乎不能訪問到對象內置的原型屬性!盡管有些瀏覽器可以訪問到對象的內置原型,但這樣做的話就只能限定了用戶必須使用那種瀏覽器。這也幾乎不可行。那么,我們可不可以通過一個函數(shù)對象來做媒介,利用該函數(shù)對象的prototype屬性來中轉這個原型,并用new操作符傳遞給新建的對象呢?其實,象這樣的代碼就可以實現(xiàn)這一目標:function anyfunc();/定義一個函數(shù)軀殼totype=Person;/將原型對象放到中轉站prototype var BillGates=new anyfunc();/新建對象的內置原型將是我們期望的原型對象不過,這個anyfunc函數(shù)只是一個軀殼,在使用過這個軀殼之后它就成了多余的東西了,而且這和直接使用構造函數(shù)來創(chuàng)建對象也沒啥不同,有點不爽??墒?,如果我們將這些代碼寫成一個通用函數(shù),而那個函數(shù)軀殼也就成了函數(shù)內的函數(shù),這
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 預防校園欺凌班會課件
- 顧客體驗課件
- 心電圖健康評估與應用
- 醫(yī)院學會管理辦法解讀
- 音樂課件的作文
- 市政污水管網(wǎng)改造項目環(huán)境影響報告書(模板)
- 城鎮(zhèn)污水管網(wǎng)建設項目投資估算方案(參考模板)
- xx河流排水防澇設施建設項目節(jié)能評估報告(參考)
- 2025年商務、清洗服務項目建議書
- 2025年差壓變送器合作協(xié)議書
- 2025年7月新疆維吾爾自治區(qū)學業(yè)水平合格性考試歷史試題(含答案)
- 建立并優(yōu)化醫(yī)院的藥品管理體系
- 農(nóng)村農(nóng)資采購與供應長期合作協(xié)議
- 反假幣培訓課件
- 2025至2030中國電壓暫降治理行業(yè)產(chǎn)業(yè)運行態(tài)勢及投資規(guī)劃深度研究報告
- 遼寧省2024年7月普通高中學業(yè)水平合格性考試化學試卷(含答案)
- 煤炭造價知識培訓
- 2025屆遼寧省大連市高新區(qū)英語七年級第二學期期末學業(yè)質量監(jiān)測模擬試題含答案
- 腫瘤全程康復管理制度
- 對患者的健康教育制度
- 2025年酒店管理專業(yè)基礎知識考試試題及答案
評論
0/150
提交評論