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

下載本文檔

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

文檔簡(jiǎn)介

JavaScript 面向?qū)ο缶幊? 第一部分: 繼承作者:lzlhero 發(fā)布:heiyeluren 時(shí)間:2005-08-25我們將向你展示 JavaScript 如何實(shí)現(xiàn)面向?qū)ο蟮恼Z(yǔ)言中的: 繼承. 同時(shí), 這些例子將向你展示如何實(shí)現(xiàn)類的封裝. 在此, 我們不會(huì)討論多態(tài)實(shí)現(xiàn).雖然 JavaScript 是腳本語(yǔ)言, 但它所支持的面向?qū)ο缶幊桃彩欠浅?qiáng)大的. 雖然它沒(méi)有類和實(shí)例, 但它有對(duì)象, 原型和隱式的繼承. 我們將會(huì)解釋如何模擬繼承及其超類與子類之間關(guān)系的形式. 原型是理解繼承概念的關(guān)鍵, 我們將會(huì)教你如何建立原型, 如何檢測(cè)一個(gè)對(duì)象是否是另外一個(gè)對(duì)象的原型, 及其 JavaScript 的模型與 Java 面向?qū)ο缶幊讨g的區(qū)別. 我們同樣會(huì)向你展示如何檢測(cè)對(duì)象所包含的各種屬性的方法. 在另外一篇文章里, 我還會(huì)詳細(xì)地講解有關(guān) 原型鏈 (prototype chain) 的知識(shí).本文大量地參考了 W 中 Object-Oriented Programming with JavaScript, Part I: Inheritance 的內(nèi)容, 許多內(nèi)容我進(jìn)行了詳細(xì)的測(cè)試和再探討, 以保證內(nèi)容不會(huì)有太大的失誤.原文地址: /js/column79/面向?qū)ο笳Z(yǔ)言的特點(diǎn)面向?qū)ο笤O(shè)計(jì)是基于以下 3 個(gè)主要原理的: 封裝, 繼承和多態(tài). 說(shuō)某種程序語(yǔ)言是支持 OO (面向?qū)ο? 設(shè)計(jì)的, 只有在它的語(yǔ)法中支持以上 3 個(gè)概念才可以這么說(shuō). 這種語(yǔ)言應(yīng)該為你提供某些方法, 以使你能很輕松地定義和使用這些范例. 封裝涉及到了將某個(gè)對(duì)象變成一個(gè) 黑盒子的概念. 當(dāng)你使用某個(gè)對(duì)象時(shí), 你不用知道它內(nèi)部是如何工作的, 你也不必理解對(duì)象是如何工作的. 這個(gè)對(duì)象只需將它絕對(duì)有用的信息以接口方式提供出來(lái). 此對(duì)象應(yīng)該給你提供友好的接口, 來(lái)讓你可以使用其有限的屬性集和方法集. 封裝還有一層意思, 那就是說(shuō)某個(gè)對(duì)象包含了它需要的每一樣?xùn)|西, 這包括數(shù)據(jù)和對(duì)于它的操作. 封裝的概念非常的強(qiáng)大, 因?yàn)樗试S將一個(gè)大的軟件項(xiàng)目有效地分配給每個(gè)開(kāi)發(fā)人員, 對(duì)于團(tuán)隊(duì)中的每個(gè)人, 他們只需要關(guān)注自己所實(shí)現(xiàn)的對(duì)象, 而不需要太多地關(guān)注于別人的實(shí)現(xiàn). 開(kāi)發(fā)項(xiàng)目中的開(kāi)銷使得開(kāi)發(fā)團(tuán)隊(duì)中成員與接口的數(shù)量按指數(shù)級(jí)別增長(zhǎng). 封裝是自 軟件危機(jī) 以來(lái)最受歡迎的 OO 設(shè)計(jì)理念.軟件的復(fù)用是 OO 設(shè)計(jì)思想中另外一個(gè)重要的特點(diǎn). 在軟件體系中實(shí)現(xiàn)此思想的主要方法就是繼承. 類就是定義對(duì)象的功能. 超類是某個(gè)新類, 或者說(shuō)是子類被建立的來(lái)源類. 一個(gè)子類從它的超類中繼承了所的方法和屬性. 實(shí)際上, 所有的子類都是被自動(dòng)地生成的, 因此節(jié)省了大量的工作. 你不需要一個(gè)一個(gè)地定義這些子類. 當(dāng)然, 你可以重載那些繼承下來(lái)的方法和屬性. 事實(shí)上, 誰(shuí)也沒(méi)有指出哪個(gè)子類要建立得和其超類一模一樣, 除非你沒(méi)有重載任何的屬性和方法.多態(tài)可能是這個(gè) 3 個(gè)概念中最復(fù)雜的一個(gè)了. 其本質(zhì)上是說(shuō), 每個(gè)對(duì)象都可以處理各種不同的數(shù)據(jù)類型. 你不必為處理不同的數(shù)據(jù)類型而建立不同的類. 其典型的例子就是畫(huà)圖的類, 你不必為實(shí)現(xiàn)畫(huà)圓, 畫(huà)矩形, 畫(huà)橢圓而編寫(xiě)不同的類. 你可以建立一個(gè)足夠聰明的類來(lái)調(diào)用特定的方法來(lái)操作特定的形狀.通過(guò)函數(shù)實(shí)現(xiàn)繼承雖然 JavaScript 不支持顯示繼承操作符, 但你可以通過(guò)其實(shí)方式實(shí)現(xiàn)隱式繼承. 對(duì)于實(shí)現(xiàn)類的繼承, 有 2 種比較常用的方式. 第一種將某個(gè)類定義成子類的方法是, 通過(guò)在負(fù)責(zé)定義子類函數(shù)的內(nèi)部調(diào)用超類的構(gòu)造函數(shù). 看下面的示例:/ 超類構(gòu)造函數(shù)function superClass() this.bye = superBye; this.hello = superHello;/ 子類構(gòu)造函數(shù)function subClass() this.inheritFrom = superClass; this.inheritFrom(); this.bye = subBye;function superHello() return Hello from superClass; function superBye() return Bye from superClass;function subBye() return Bye from subClass;/ 測(cè)試構(gòu)造特性的函數(shù)function printSub() var newClass = new subClass(); alert(newClass.bye(); alert(newClass.hello();當(dāng)你運(yùn)行上面的 printSub 函數(shù)時(shí), 它會(huì)依次執(zhí)行 subBuy 和 superHello 函數(shù). 我們可以看到, bye 和 hello 方法最先在 superClass 中被定義了. 然而, 在 subClass 中, bye 方法又被重載了, subClass 構(gòu)造函數(shù)頭兩行的功能只是做了一個(gè)簡(jiǎn)單的原始的繼承操作, 但它是通過(guò)顯示執(zhí)行 inheritFrom 方法來(lái)完成的繼承操作. 繼承的過(guò)程先是將 superClass 的對(duì)象原型賦給 subClass 下的 inheritFrom 方法, 然后在執(zhí)行完 superClass 的構(gòu)造函數(shù)后, superClass 的屬性就被自動(dòng)地加到了 subClass 的屬性列表中.這主要是由于在 subClass 中通過(guò) this 來(lái)調(diào)用的 inheritFrom (也就是 superClass) 構(gòu)造函數(shù)造成的, 通過(guò)此種方式調(diào)用 superClass 構(gòu)造函數(shù)時(shí), JavaScript 解釋器會(huì)把 superClass 中的 this 與 subClass 中的 this 理解成位于同一個(gè)作用域下的 this 關(guān)鍵字, 所以就產(chǎn)生了繼承的效果.另外, 需要說(shuō)明的是, 對(duì)于任何一個(gè)實(shí)例化的對(duì)象, 你任意地為它添加屬性或方法, 如下所示: var newClass = new subClass(); newClass.addprop = added property to instance object;很明顯, 通過(guò)此種方式添加的屬性和方法只對(duì)當(dāng)前實(shí)例化對(duì)象有效, 不會(huì)影響所有的同類型對(duì)象實(shí)例. 無(wú)疑, 它是你創(chuàng)造的一個(gè)獨(dú)一無(wú)二的對(duì)象實(shí)例.通過(guò)原型實(shí)現(xiàn)繼承第二種, 也是更強(qiáng)大的方法是通過(guò)建立一個(gè)超類對(duì)象, 然后將其賦值給子類對(duì)象的 prototype 屬性, 以此方式來(lái)建立子類的繼承. 假設(shè)我們的超類是 superClass, 子類是 subClass. 其 prototype 的賦值格式如下:subCtotype = new superClass;對(duì)于原型繼承的實(shí)現(xiàn)方式, 讓我們剛前面的代碼改寫(xiě)一下, 示例如下:/ 超類構(gòu)造函數(shù)function superClass() this.bye = superBye; this.hello = superHello;/ 子類構(gòu)造函數(shù)function subClass() this.bye = subBye;subCtotype = new superClass;function superHello() return Hello from superClass; function superBye() return Bye from superClass;function subBye() return Bye from subClass;/ 測(cè)試構(gòu)造特性的函數(shù)function printSub() var newClass = new subClass(); alert(newClass.bye(); alert(newClass.hello();我們可以看到, 除了將前面第一種繼承方式中 subClass 中的前 2 行內(nèi)容, 換成函數(shù)外的 prototype 賦值語(yǔ)句之外, 沒(méi)有其它任何的變化, 但代碼的執(zhí)行效果和前面是一樣的.為已經(jīng)建立的對(duì)象添加屬性通過(guò)原型實(shí)現(xiàn)的繼承比通過(guò)函數(shù)實(shí)現(xiàn)的繼承更好, 因?yàn)樗С謩?dòng)態(tài)繼承. 你可以在構(gòu)造函數(shù)已經(jīng)完成之后, 再通過(guò) prototype 屬性定義超類的其它方法和屬性, 并且其下的子類對(duì)象會(huì)自動(dòng)地獲得新的方法和屬性. 下面是示例, 你可以看到它的效果.function superClass() this.bye = superBye; this.hello = superHello;function subClass() this.bye = subBye;subCtotype = new superClass;function superHello() return Hello from superClass; function superBye() return Bye from superClass;function subBye() return Bye from subClass;var newClass = new subClass();/*/ 動(dòng)態(tài)添加的 blessyou 屬性superCtotype.blessyou = superBlessyou;function superBlessyou() return Bless You from SuperClass;/*/function printSub() alert(newClass.bye(); alert(newClass.hello(); alert(newClass.blessyou();這就是我們經(jīng)??吹降臑閮?nèi)部對(duì)象, 如 String, Math 等再添加其它屬性和方法的技巧. 對(duì)于任何的內(nèi)部對(duì)象和自定義對(duì)象, 你都也可以通過(guò) prototype 來(lái)重載其下的屬性和方法. 那么在調(diào)用執(zhí)行時(shí), 它將調(diào)用你所定義的方法和屬性. 下面是示例:/ 為內(nèi)部 String 對(duì)象添加方法Stotype.myMethod = function() return my define method;/ 為內(nèi)部 String 對(duì)象重載方法Stotype.toString = function() return my define toString method;var myObj = new String(foo);alert(myObj.myMethod();alert(myObj);alert(foo.toString();另外需要注意的是, 所有 JavaScript 內(nèi)部對(duì)的 prototype 屬性都是只讀的. 你可以像上面那樣為內(nèi)部對(duì)象的原型添加或重載屬性和方法,但不能更改該內(nèi)部對(duì)象的 prototype 原型. 然而, 自定義對(duì)象可以被賦給新的原型. 也就是說(shuō), 像下面這樣做是沒(méi)有意思的.function Employee() this.dept = HR; this.manager = John Johnson;Stotype = new Employee;var myString = new String(foo);上面的程序在運(yùn)行之后不會(huì)報(bào)錯(cuò), 但顯然, 如果你調(diào)用 myString.dept 將會(huì)得到一個(gè)非定義的值.另外, 一個(gè)經(jīng)常使用的是 prototype 下的 isPrototypeOf() 方法, 它主要用來(lái)判斷指定對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈中. 語(yǔ)法如下:totype.isPrototypeOf(0bject2);上面的格式是用來(lái)判斷 Object2 是否出現(xiàn) Object1 的原型鏈中. 示例如下:function Person() = Rob Roberson; this.age = 31;function Employee() this.dept = HR; this.manager = John Johnson;Etotype = new Person();var Ken = new Employee();當(dāng)執(zhí)行 Etotype.isPrototypeOf(Ken), Ptotype.isPrototypeOf(Ken) 和 Ototype.isPrototypeOf(Ken) 時(shí), 結(jié)果都會(huì)返回 true.用于 Netscape 下的特定繼承檢測(cè)在 Netscape 瀏覽器 4.x 到 6, 及其 Mozilla 系列瀏覽中, JavaScript 將對(duì)象間的原型關(guān)系存儲(chǔ)在一個(gè)特殊的內(nèi)部屬性對(duì)象中, _proto_ (前后是 2 個(gè)下劃線). 下面是一個(gè)示例:function Shape() this.borderWidth = 5;function Square() this.edge = 12;Stotype = new Shape;myPicture = new Square;alert(myPicture._proto_);alert(myPicture.borderWidth);由于腳本執(zhí)行過(guò) Stotype = new Shape 語(yǔ)句, 所以 myPicture 具有了一個(gè)指向 Shape 對(duì)象的內(nèi)部屬性 _proto_. 在腳本的執(zhí)行過(guò)程中, 當(dāng)要獲取對(duì)象的某個(gè)屬性值, 并且此對(duì)象是通過(guò)原型賦值而建立的某個(gè)對(duì)象, 在自身并沒(méi)有對(duì)某個(gè)屬性進(jìn)行定義時(shí), JavaScript 解析器會(huì)查看它的 _proto_ 屬性對(duì)象, 也就它的原型對(duì)象, 然后枚舉其原型中的所有屬性, 而得出的結(jié)果要么是有這個(gè)屬性, 要么是沒(méi)有這個(gè)屬性. 如果沒(méi)有此屬性, 再枚舉原型對(duì)象下面的原型對(duì)象, 直到此過(guò)程真正的結(jié)束. 而所有的這些 JavaScript 引擎內(nèi)部的操作, 我們是不會(huì)知道的, 下面的內(nèi)容就是對(duì)這個(gè)問(wèn)題的解釋.其實(shí), 對(duì)于所有的自定義對(duì)象, 無(wú)論它有沒(méi)有使用過(guò) prototype 賦值操作, 它都具有一個(gè) _proto_ 內(nèi)部對(duì)象. 而如果某個(gè)對(duì)象是通過(guò)多層 prototype 繼承 來(lái)的, 所有的 繼承 而來(lái)的屬性卻可以通過(guò)簡(jiǎn)單的一層循環(huán)遍歷出來(lái), 而不需要使用什么遞歸算法, 因?yàn)?JavaScript 引擎自動(dòng)給我們做了. 示例如下:function Shape() this.borderWidth = 5;function Square() this.edge = 12;function RoundSquare() this.radio = 0.5;Stotype = new Shape;RoundStotype = new Square;var myPicture = new RoundSquare;for (property in myPicture._proto_) alert(property);我們或者還可以通過(guò)更改后面的循環(huán), 來(lái)遍歷某個(gè)子類對(duì)象繼承來(lái)的所有屬性, 如下:for (property in RoundStotype) alert(property);如果你不怕麻煩, 我們甚至還可以通過(guò)級(jí)連的方式, 取出其構(gòu)造函數(shù)中定義的原始屬性值.alert(myPicture._proto_._proto_.borderWidth);無(wú)論你是否修改過(guò)此屬性值, 通過(guò)上面語(yǔ)句所取出的屬性值都是原始定義值. 讓我們沿著這個(gè)思路再往下看, 下面的代碼涉及到另外一個(gè)問(wèn)題, 這個(gè)問(wèn)題和原型鏈 (prototype chain) 有關(guān). 代碼如下:function State() function City() Ctotype = new State;function Street() Stotype = new City;var UniversityAvenue = new Street();function tryIt() alert(UniversityAvenue._proto_= Stotype); alert(UniversityAvenue._proto_._proto_= Ctotype); alert(UniversityAvenue._proto_._proto_._proto_ = Stotype); alert(UniversityAvenue._proto_._proto_._proto_. _proto_= Ototype); alert(UniversityAvenue._proto_._proto_._proto_. _proto_._proto_= null);當(dāng)執(zhí)行 tryIt 函數(shù)時(shí), 所有的顯示均為 true. 也就是說(shuō), 子類對(duì)象的 prototype._proto_ 總是等于超類對(duì)象的 prototype 屬性; 超類對(duì)象的 prototype._proto_ 總是等于 Ototype; Ototype._proto_ 總是為 null; 而實(shí)例對(duì)象的 _proto_ 總是等于其類對(duì)象的 prototype, 這就是為什么任何自定義對(duì)象都具有 _proto_ 屬性的原因. 對(duì)于上面的敘述, 其對(duì)應(yīng)的代碼如下:Stotype._proto_ = Ctotype / trueStotype._proto_ = Ototype / trueOtotype._proto_ = null / trueUniversityAvenue._proto_ = Stotype / true模擬實(shí)現(xiàn) instanceOf 函數(shù)根據(jù)上一節(jié)的內(nèi)容, 我們了解了有關(guān) Netscape 所支持的 _proto_ 特性的內(nèi)容. 這一節(jié), 我們將利用此特性來(lái)創(chuàng)建自己的實(shí)例對(duì)象檢測(cè)函數(shù).許多時(shí)候, 我們都需要判斷某個(gè)對(duì)象是否是由某個(gè)類來(lái)定義的, 在其它的語(yǔ)言里, 你可以通過(guò) instanceOf 函數(shù)來(lái)實(shí)現(xiàn)此判斷. 在 JavaScript 中同樣提供了一個(gè) instanceof 運(yùn)行符, 而在 _proto_ 的基礎(chǔ)上, 我們完全可以自己定義一個(gè)同樣的函數(shù), 雖然這看上去是在重復(fù)勞動(dòng), 但有助于我們更深刻地了解有關(guān) _proto_ 的知識(shí). 下面的代碼只是用來(lái)說(shuō)明功能, 在實(shí)際的應(yīng)用中, 你不需要重復(fù)定義 instanceOf 函數(shù), 使用 instanceof 運(yùn)算符即可.function instanceOf(object, constructorFunction) while (object != null) if (object = constructorFtotype) return true object = object._proto_; return false;function State() function City() Ctotype = new State;function Street() Stotype = new City;var UniversityAvenue = new Street();function demo() alert(instanceOf(UniversityAvenue, Street) is + instanceOf(UniversityAvenue, Street); alert(instanceOf(UniversityAvenue, City) is + instanceOf(UniversityAvenue, City); alert(instanceOf(UniversityAvenue, State) is + instanceOf(UniversityAvenue, State);你會(huì)看到所有的運(yùn)行結(jié)果全部為 true, 其原理和上一節(jié)的級(jí)連判斷相等如出一轍. 實(shí)際證明, 它的運(yùn)行結(jié)果和 instanceof 運(yùn)行符的運(yùn)行結(jié)果是一致的.你可以通過(guò) constructor 屬性來(lái)檢測(cè)任意對(duì)象的超類, 此屬性返回通過(guò) new 運(yùn)算符創(chuàng)建新對(duì)象時(shí)所調(diào)用的構(gòu)造函數(shù), 返回值是 Function 對(duì)象類型. 因?yàn)?Object 內(nèi)部對(duì)象是支持 constructor 屬性的, 并且有的對(duì)象 (包括內(nèi)部對(duì)象和自定義對(duì)象) 都是由 Object 繼承而來(lái)的, 所以所有的對(duì)象都支持此屬性. 讓我們?cè)倏匆幌孪旅娴睦?function Employee() this.dept = HR; this.manager = John Johnson;function printProp() var Ken = new Employee(); alert(Ken.constructor);調(diào)用完 printProp 函數(shù)之后, 你會(huì)看到彈出框中顯示的是 Employee 函數(shù)的定義文本, 其實(shí) Ken.constructor 的返回值本身是 Function 對(duì)象類型, 而在 alert 時(shí)被隱含地調(diào)用了 toString 方法. 對(duì)于類對(duì)象本身, 你同樣可以調(diào)用 prototype.constructor 來(lái)取出其構(gòu)造函數(shù).對(duì)象的分類和打印JavaScript 支持 3 種主要類型的對(duì)象: 內(nèi)部對(duì)象, 宿主對(duì)象, 自定義對(duì)象, 可能還有特殊的外部對(duì)象, 如: ActiveX 對(duì)象或 XPCOM 對(duì)象. 內(nèi)部對(duì)象被 JavaScript 語(yǔ)言本身所支持, 如: Object, Math, Number 對(duì)象等. 所有的內(nèi)部對(duì)象的共同特點(diǎn)是以大寫(xiě)字母開(kāi)頭, 并且它們是大小寫(xiě)敏感的. 如果你想使用數(shù)學(xué)常量 PI, 必須寫(xiě)成 Math.PI, 你如果寫(xiě)成 math.PI, JavaScript 會(huì)顯示錯(cuò)誤. 宿主對(duì)象是被瀏覽器支持的, 目的是為了能和被瀏覽的文檔可以交互, 如: document, window 和 frames. 宿主對(duì)象的特點(diǎn)是所有對(duì)象全部以小寫(xiě)字母開(kāi)頭. 因?yàn)?JavaScript 本身就是大小寫(xiě)敏感的, 所以你同樣不能將大小寫(xiě)搞混. 剩下要說(shuō)的就只是自定義對(duì)象了, 你可以隨便將你的對(duì)象定義成小寫(xiě)或大小寫(xiě), 但是一定要符合基本的命名規(guī)范. 如下所示, 這就是一個(gè)自定義對(duì)象:function employee() this.dept = HR; this.manager = John Johnson;function printProp() var ken = new Employee(); for (property in ken) alert(property); 前面我們已經(jīng)提到過(guò), 所有的內(nèi)部對(duì)象和自定義對(duì)象都是從 Object 對(duì)象繼承而來(lái)的, 它是所有對(duì)象的超類對(duì)象. 你可建立一個(gè) Object 對(duì)象的實(shí)例. 如下:var myObject = new Object();Object 類型的對(duì)象有許多的屬性和方法, 你可以查看相關(guān)的手冊(cè). 上面只是定義了一個(gè)最簡(jiǎn)單的空對(duì)象, 你還可以為 Object 構(gòu)造函數(shù)傳入?yún)?shù), 它會(huì)返回相應(yīng)類型值的實(shí)例化對(duì)象. 記住, 返回值的類型是某種對(duì)象類型的 (如: String, Number 或 Object). 這種方式和直接通過(guò)賦值字符串或數(shù)值常量不同, 主要表示在類型方面. 如下所示:var myObject = new Object(foo); / 返回值類型為 objectvar myObject = new String(foo); / 返回值類型為 object, 效果同上與var myObject = foo; / 返回值類型為 string你可以從調(diào)試器的 type 列中看出這個(gè)細(xì)微的差別, 它是簡(jiǎn)單類型與對(duì)象類型之間的區(qū)別. 但是, 你通過(guò) alert 調(diào)用是看出不這些內(nèi)部差別的, 因?yàn)樵谡{(diào)用 alert 的過(guò)程中, 所有的對(duì)象類型值都會(huì)被自動(dòng)調(diào)用 toString 方法進(jìn)行字符串類型轉(zhuǎn)換, 轉(zhuǎn)換規(guī)則在 JavaScript 手冊(cè)中有說(shuō)明. 如果你 alert 的是某個(gè)自定義對(duì)象, 并且它沒(méi)有定義 toString 方法, 那么它的返回值將為 object Object. 對(duì)于 Math 對(duì)象, 當(dāng)你查看其 Math.constructor 屬性時(shí), 你會(huì)得到一個(gè)不同于其它內(nèi)部對(duì)象的內(nèi)容為 function Object(). 的對(duì)象構(gòu)造函數(shù), 這與其它對(duì)象返回 function Function(). 的構(gòu)造函數(shù)很不相同. 原因很簡(jiǎn)單, 因?yàn)?Math 對(duì)象是不能通過(guò) new 運(yùn)算符進(jìn)行創(chuàng)建的.另外, 如果傳入 Object 構(gòu)造函數(shù)中的值是一個(gè)對(duì)象, 它將原封不動(dòng)地將該對(duì)象返回. 記住, 此操作只是一個(gè)引用, 而不是復(fù)制.請(qǐng)求對(duì)象的屬性在前面的示例代碼中, 已經(jīng)出現(xiàn)過(guò)以循環(huán)方式枚舉對(duì)象屬性的示例. 其實(shí), 通過(guò) for.in 語(yǔ)句, 無(wú)論是任何對(duì)象和數(shù)組, 其下的元素, 屬性和方法都可以遍歷出來(lái). 示例如下:function employee() this.dept = HR; this.manager = John Johnson;function printProp() var ken = new employee(); for (property in ken) alert(property + : + kenproperty); 在遍歷測(cè)試過(guò)程中, 你會(huì)發(fā)現(xiàn), 對(duì)于自定義對(duì)象和宿主對(duì)象一般都可以枚舉出其下的屬性, 而對(duì)于內(nèi)部對(duì)象, 幾乎沒(méi)有什么屬性可以遍歷出來(lái), 為什么要說(shuō)幾乎呢? 因?yàn)閷?duì)于 Mozilla 內(nèi)核的瀏覽和 IE 內(nèi)核的瀏覽器, 其 JavaScript 引擎有不同, Mozilla 下可以枚舉出部分內(nèi)容, 而枚舉的原則不得而知.對(duì)于每一個(gè)對(duì)象, 你還可以使用 hasOwnProperty 方法來(lái)檢測(cè)其是否具有某個(gè)屬性或方法. 由于 hasOwnProperty 是 Object 對(duì)象下的方法, 因此所有的對(duì)象都具有此方法. 但是, 需要注意的是, 此方法只能檢測(cè)通過(guò) this 關(guān)鍵字定義的成員, 如果某個(gè)成員是通過(guò)原型鏈定義的, 那么此方法將返回 false. 也就是說(shuō), 通過(guò) prototype 繼承來(lái)的屬性和方法, 及其通過(guò) prototype 定義的屬性和方法, 都是不能通過(guò) hasOwnProperty 來(lái)進(jìn)行檢測(cè)的. 由此, 我們可以看出, 通過(guò) this關(guān)鍵字定義的屬性和方法是同對(duì)象本身處于同一個(gè)地址空間內(nèi)的; 而通過(guò) prototype 定義的屬性和方法, 是通過(guò)所謂的 原型鏈 進(jìn)行管理的, 其下的的屬性和方法不位于同一個(gè)地址空間之間, 當(dāng)其調(diào)用這種屬性或方法時(shí), 必須通過(guò) 鏈表 才能索引到其下的某個(gè)屬性或方法. 也就說(shuō), 調(diào)用以原型方式定義的屬性和方法會(huì)有一個(gè)類似于鏈表的 回溯 操作.和 hasOwnProperty 差不多, 對(duì)于對(duì)象中的每個(gè)屬性, 我們還可以通過(guò) propertyIsEnumerable 來(lái)測(cè)試它是否可以被枚舉出來(lái). 如下所示:function Employee1() this.dept = HR; this.manager = John Johnson;

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 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)論