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

下載本文檔

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

文檔簡(jiǎn)介

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

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

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

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

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

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

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

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

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

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

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

12、對(duì)象的實(shí)例。比如,現(xiàn)在有一個(gè) " 動(dòng)物 " 對(duì)象的構(gòu)造函數(shù), function Animal( this .species = "動(dòng)物 " ;還有一個(gè) " 貓 " 對(duì)象的構(gòu)造函數(shù), function Cat(name, color this .name = name;this .color = color;怎樣才能使 " 貓 " 繼承 "動(dòng)物 " 呢 ?1. 構(gòu)造函數(shù)綁定最簡(jiǎn)單的方法,大概就是使用 call 或 apply 方法,將父對(duì)象的構(gòu)造函數(shù)綁定在子對(duì)象上,也就是在 子對(duì)象構(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; / 動(dòng)物 2. prototype模式更常見的做法,則是使用 prototype 屬性。如果 " 貓 " 的 prototype 對(duì)象,指向一個(gè) Anim al 的實(shí)例,那么所有 " 貓 " 的實(shí)例,就能繼承 Anim al

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

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

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

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

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

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

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

21、otype 屬性。 這等于是在子對(duì)象 上打開一條通道,可以直接調(diào)用父對(duì)象的方法。這一行放在這里,只是為了實(shí)現(xiàn)繼承的完備性,純屬 備用性質(zhì)。 6. 拷貝繼承 上面是采用 prototype 對(duì)象,實(shí)現(xiàn)繼承。我們也可以換一種思路,純粹采用"拷貝"方法實(shí)現(xiàn)繼承。 簡(jiǎn)單說,如果把父對(duì)象的所有屬性和方法,拷貝進(jìn)子對(duì)象,不也能夠?qū)崿F(xiàn)繼承嗎? 首先,還是把 Animal 的所有不變屬性,都放到它的 prototype 對(duì)象上。 function Animal( Atotype.species = "動(dòng)物" 然后,再寫一個(gè)函數(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; 這個(gè)函數(shù)的作用,就是將父對(duì)象的 prototype 對(duì)象中的屬性,一一拷貝給 Child 對(duì)象的 prototype 對(duì)象。 使用的時(shí)候,這樣寫: extend2(Cat, Animal; var cat1 = new Cat("大毛","黃色" alert(cat1.species; / 動(dòng)物 三. Javascript

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

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

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

溫馨提示

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

評(píng)論

0/150

提交評(píng)論