JavaScript面向?qū)ο缶幊躺钊敕治鯻第1頁
JavaScript面向?qū)ο缶幊躺钊敕治鯻第2頁
JavaScript面向?qū)ο缶幊躺钊敕治鯻第3頁
JavaScript面向?qū)ο缶幊躺钊敕治鯻第4頁
JavaScript面向?qū)ο缶幊躺钊敕治鯻第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、JavaScript 面向?qū)ο缶幊躺钊敕治鲆?. Javascript 面向?qū)ο缶幊?封裝Javascript 是一種基于對象 (object-based的語言,你遇到的所有東西幾乎都是對象。但是,它又 不是一種真正的面向?qū)ο缶幊?(OOP語言,因?yàn)樗恼Z法中沒有 class(類 。那么,如果我們要把 " 屬性 "(property和 " 方法 "(method ,封裝成一個對象,甚至要從原型對象生 成一個實(shí)例對象,我們應(yīng)該怎么做呢 ?1. 生成對象的原始模式假定我們把貓看成一個對象,它有 " 名字 " 和 " 顏色 &qu

2、ot; 兩個屬性。var Cat = name : '' ,color : '' 現(xiàn)在,我們需要根據(jù)這個原型對象,生成兩個實(shí)例對象。var cat1 = ; /創(chuàng)建一個空對象 = "大毛 " /按照原型對象的屬性賦值cat1.color = "黃色 " ;var cat2 = ; = "二毛 " ;cat2.color = "黑色 "好了,這就是最簡單的封裝了。但是,這樣的寫法有兩個缺點(diǎn),一是如果多生成幾個實(shí)例,寫起來就 非常麻煩 ; 二是實(shí)例與原

3、型之間,沒有任何辦法,可以看出有什么聯(lián)系。2. 原始模式的改進(jìn)我們可以寫一個函數(shù),解決代碼重復(fù)的問題。function Cat(name, color return name: name,color: color然后生成實(shí)例對象,就等于是在調(diào)用函數(shù):var cat1 = Cat("大毛 "," 黃色 " ;var cat2 = Cat("二毛 "," 黑色 "這種方法的問題依然是, cat1和 cat2之間沒有內(nèi)在的聯(lián)系,不能反映出它們是同一個原型對象的實(shí) 例。3. 構(gòu)造函數(shù)模式為了解決從原型對象生成實(shí)例的問題,

4、Javascript 提供了一個構(gòu)造函數(shù) (Constructor模式。所謂 " 構(gòu)造函數(shù) " , 其實(shí)就是一個普通函數(shù), 但是內(nèi)部使用了 this 變量。 對構(gòu)造函數(shù)使用 new 運(yùn)算符, 就能生成實(shí)例,并且 this 變量會綁定在實(shí)例對象上。比如,貓的原型對象現(xiàn)在可以這樣寫,function Cat(name, color this .name = name;this .color = color;我們現(xiàn)在就可以生成實(shí)例對象了。var cat1 = new Cat("大毛 ", "黃色 " ;var cat2 = new Cat(

5、"二毛 ", "黑色 " ;alert(; /大毛alert(cat1.color; /黃色這時 cat1和 cat2會自動含有一個 constructor 屬性,指向它們的構(gòu)造函數(shù)。alert(cat1.constructor = Cat; /truealert(cat2.constructor = Cat; /trueJavascript 還提供了一個 instanceof 運(yùn)算符,驗(yàn)證原型對象與實(shí)例對象之間的關(guān)系。alert(cat1 instanceof Cat; /truealert(cat2 instanceof Cat;

6、/true4. 構(gòu)造函數(shù)模式的問題構(gòu)造函數(shù)方法很好用,但是存在一個浪費(fèi)內(nèi)存的問題。請看, 我們現(xiàn)在為 Cat 對象添加一個不變的屬性 "type"(種類 , 再添加一個方法 eat(吃老鼠 。 那么, 原型對象 Cat 就變成了下面這樣:function Cat(name, color this .name = name;this .color = color;this .type = "貓科動物 " ;this .eat = function ( alert("吃老鼠 " ; ;還是采用同樣的方法,生成實(shí)例:var cat1 = n

7、ew Cat("大毛 "," 黃色 " ;var cat2 = new Cat ("二毛 "," 黑色 " ;alert(cat1.type; /貓科動物cat1.eat(; /吃老鼠表面上好像沒什么問題, 但是實(shí)際上這樣做, 有一個很大的弊端。 那就是對于每一個實(shí)例對象, type 屬性和 eat(方法都是一模一樣的內(nèi)容,每一次生成一個實(shí)例,都必須為重復(fù)的內(nèi)容,多占用一些內(nèi) 存。這樣既不環(huán)保,也缺乏效率。alert(cat1.eat = cat2.eat; /false能不能讓 type 屬性和 eat(方法在內(nèi)

8、存中只生成一次, 然后所有實(shí)例都指向那個內(nèi)存地址呢 ? 回答是 可以的。5. Prototype模式Javascript 規(guī)定,每一個構(gòu)造函數(shù)都有一個 prototype 屬性,指向另一個對象。這個對象的所有屬 性和方法,都會被構(gòu)造函數(shù)的實(shí)例繼承。這意味著,我們可以把那些不變的屬性和方法,直接定義在 prototype 對象上。 function Cat(name, color this .name = name;this .color = color;Ctotype.type = "貓科動物 " ;Ctotype.eat = function (

9、alert("吃老鼠 " ; 然后,生成實(shí)例。var cat1 = new Cat("大毛 "," 黃色 " ;var cat2 = new Cat("二毛 "," 黑色 " ;alert(cat1.type; /貓科動物cat1.eat(; /吃老鼠這時所有實(shí)例的 type 屬性和 eat(方法,其實(shí)都是同一個內(nèi)存地址,指向 prototype 對象,因此就 提高了運(yùn)行效率。alert(cat1.eat = cat2.eat; /true6. Prototype模式的驗(yàn)證方法6.1 isPro

10、totypeOf(這個方法用來判斷,某個 proptotype 對象和某個實(shí)例之間的關(guān)系。alert(Ctotype.isPrototypeOf(cat1; /true alert(Ctotype.isPrototypeOf(cat2; /true6.2 hasOwnProperty(每個實(shí)例對象都有一個 hasOwnProperty(方法,用來判斷某一個屬性到底是本地屬性,還是繼承 自 prototype 對象的屬性。alert(cat1.hasOwnProperty("name" /truealert(cat1.hasOwnProperty(&q

11、uot;type" /false6.3 in運(yùn)算符in 運(yùn)算符可以用來判斷,某個實(shí)例是否含有某個屬性,不管是不是本地屬性。alert("name" in cat1; /truealert("type" in cat1; / truein 運(yùn)算符還可以用來遍歷某個對象的所有屬性。for (var prop in cat1 alert("cat1"+prop+"="+cat1prop; 二 . Javascript 面向?qū)ο缶幊?構(gòu)造函數(shù)的繼承本節(jié)主要介紹,如何生成一個 " 繼承 " 多個

12、對象的實(shí)例。比如,現(xiàn)在有一個 " 動物 " 對象的構(gòu)造函數(shù), function Animal( this .species = "動物 " ;還有一個 " 貓 " 對象的構(gòu)造函數(shù), function Cat(name, color this .name = name;this .color = color;怎樣才能使 " 貓 " 繼承 "動物 " 呢 ?1. 構(gòu)造函數(shù)綁定最簡單的方法,大概就是使用 call 或 apply 方法,將父對象的構(gòu)造函數(shù)綁定在子對象上,也就是在 子對象構(gòu)造函數(shù)中加一行

13、:function Cat(name, color Animal.apply(this , arguments;this .name = name;this .color = color;var cat1 = new Cat("大毛 ", "黃色 " ;alert(cat1.species; / 動物 2. prototype模式更常見的做法,則是使用 prototype 屬性。如果 " 貓 " 的 prototype 對象,指向一個 Anim al 的實(shí)例,那么所有 " 貓 " 的實(shí)例,就能繼承 Anim al

14、了。Ctotype = new Animal(;Ctotype.constructor = Cat;var cat1 = new Cat("大毛 "," 黃色 " ;alert(cat1.species; / 動物代碼的第一行,我們將 Cat 的 prototype 對象指向一個 Anim al 的實(shí)例。Ctotype = new Animal(;它相當(dāng)于完全刪除了 prototype 對象原先的值, 然后賦予一個新值。 但是, 第二行又是什么意思呢 ? Ctotype.constructor = Cat;

15、原來,任何一個 prototype 對象都有一個 constructor 屬性,指向它的構(gòu)造函數(shù)。也就是說, Ctotype 這個對象的 constructor 屬性,是指向 Cat 的。我們在前一步已經(jīng)刪除了這個 prototype 對象原來的值, 所以新的 prototype 對象沒有 constructor 屬性,所以我們必須手動加上去,否則后面的 " 繼承鏈 " 會出問題。這就是第二行的意思??傊?這是很重要的一點(diǎn),編程時務(wù)必要遵守。下文都遵循這一點(diǎn),即如果替換了 prototype 對象, totype = ;那么,下一步必然是為新的 pro

16、totype 對象加上 constructor 屬性,并將這個屬性指回原來的構(gòu)造 函數(shù)。totype.constructor = o;3. 直接繼承 prototype由于 Anim al 對象中,不變的屬性都可以直接寫入 Anim totype 。所以,我們也可以讓 Cat(跳過 Animal(,直接繼承 Anim totype ?,F(xiàn)在,我們先將 Anim al 對象改寫:function Animal( Atotype.species = "動物 "然后,將 Cat 的 prototype 對象,然后指向 Anim a

17、l 的 prototype 對象,這樣就完成了繼承。Ctotype = Atotype;CatCtotype.constructor = Cat;var cat1 = new Cat("大毛 "," 黃色 " ;alert(cat1.species; /動物與前一種方法相比,這樣做的優(yōu)點(diǎn)是效率比較高 (不用執(zhí)行和建立 Anim al 的實(shí)例了 ,比較省內(nèi)存。 缺點(diǎn)是 Ctotype 和 Anim totype 現(xiàn)在指向了同一個對象, 那么任何對 Ctotype 的修改,都會反映

18、到 Anim totype 。所以,上面這一段代碼其實(shí)是有問題的。請看第二行Ctotype.constructor = Cat;這一句實(shí)際上把 Anim totype 對象的 constructor 屬性也改掉了 ! alert(Atotype.constructor; /Cat4. 利用空對象作為中介由于 " 直接繼承 prototype" 存在上述的缺點(diǎn),所以可以利用一個空對象作為中介。var F = function (;F.prototype = Atotype;Ctotype =

19、new F(; Ctotype.constructor = Cat; F 是空對象,所以幾乎不占內(nèi)存。這時,修改 Cat 的 prototype 對象,就不會影響到 Animal 的 prototype 對象。 alert(Atotype.constructor; / Animal 5. prototype 模式的封裝函數(shù) 我們將上面的方法,封裝成一個函數(shù),便于使用。 function extend(Child, Parent var F = function ( ; F.prototype = Ptotype; Ctotype

20、= new F(; Ctotype.constructor = Child; Child.uber = Ptotype; 使用的時候,方法如下 extend(Cat, Animal; var cat1 = new Cat("大毛", "黃色" alert(cat1.species; / 動物 這個 extend 函數(shù),就是 YUI 庫如何實(shí)現(xiàn)繼承的方法。 另外,說明一點(diǎn)。函數(shù)體最后一行 Child.uber = Ptotype; 意思是為子對象設(shè)一個 uber 屬性, 這個屬性直接指向父對象的 prot

21、otype 屬性。 這等于是在子對象 上打開一條通道,可以直接調(diào)用父對象的方法。這一行放在這里,只是為了實(shí)現(xiàn)繼承的完備性,純屬 備用性質(zhì)。 6. 拷貝繼承 上面是采用 prototype 對象,實(shí)現(xiàn)繼承。我們也可以換一種思路,純粹采用"拷貝"方法實(shí)現(xiàn)繼承。 簡單說,如果把父對象的所有屬性和方法,拷貝進(jìn)子對象,不也能夠?qū)崿F(xiàn)繼承嗎? 首先,還是把 Animal 的所有不變屬性,都放到它的 prototype 對象上。 function Animal( Atotype.species = "動物" 然后,再寫一個函數(shù),實(shí)現(xiàn)屬性拷貝的目的。 f

22、unction extend2(Child, Parent var p = Ptotype; var c = Ctotype; for (var i in p ci = pi; c.uber = p; 這個函數(shù)的作用,就是將父對象的 prototype 對象中的屬性,一一拷貝給 Child 對象的 prototype 對象。 使用的時候,這樣寫: extend2(Cat, Animal; var cat1 = new Cat("大毛","黃色" alert(cat1.species; / 動物 三. Javascript

23、 面向?qū)ο缶幊蹋悍菢?gòu)造函數(shù)的繼承 本節(jié)介紹不使用構(gòu)造函數(shù)實(shí)現(xiàn)"繼承"。 1. 什么是"非構(gòu)造函數(shù)"的繼承? 比如,現(xiàn)在有一個對象,叫做"中國人"。 var Chinese = nation: '中國' 還有一個對象,叫做"醫(yī)生"。 var Doctor = career: '醫(yī)生' 請問怎樣才能讓"醫(yī)生"去繼承"中國人",也就是說,我怎樣才能生成一個"中國醫(yī)生"的對象? 這里要注意,這兩個對象都是普通對象,不是構(gòu)造函數(shù),無法

24、使用構(gòu)造函數(shù)方法實(shí)現(xiàn)"繼承"。 2. object(方法 json 格式的發(fā)明人 Douglas Crockford,提出了一個 object(函數(shù),可以做到這一點(diǎn)。 function object(o function F( F.prototype = o; return new F(; 這個 object(函數(shù),其實(shí)只做一件事,就是把子對象的 prototype 屬性,指向父對象,從而使得子 對象與父對象連在一起。 使用的時候,第一步先在父對象的基礎(chǔ)上,生成子對象: var Doctor = object(Chinese; 然后,再加上子對象本身的屬性: Doctor.

25、career = '醫(yī)生' 這時,子對象已經(jīng)繼承了父對象的屬性了。 alert(Doctor.nation; /中國 3. 淺拷貝 除了使用"prototype 鏈"以外,還有另一種思路:把父對象的屬性,全部拷貝給子對象,也能實(shí)現(xiàn)繼 承。 下面這個函數(shù),就是在做拷貝: function extendCopy(p var c = ; for (var i in p ci = pi; c.uber = p; return c; 使用的時候,這樣寫: var Doctor = extendCopy(Chinese; Doctor.career = '醫(yī)生' alert(Doctor.nation; / 中國 但是,這樣的拷貝有一個問題。那就是,如果父對象的屬性等于數(shù)組或另一個對象,那么實(shí)際上,子 對象獲得的只是一個內(nèi)存地址,而不是真正拷貝,因此存在父對象被篡改的可能。 請看,現(xiàn)在給 Chinese 添加一個"出生地"屬性,它的值是一個數(shù)組。 Chinese.birthPlaces = '北京','上海','香港' 通過 extendCopy(函數(shù),D

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論