理解js的prototype原型對象

來源:互聯網
上載者:User

標籤:javascript   prototype   

我們建立的每個函數都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個對象,而這個對象的用途是包含可以由特定類型的所有執行個體共用的屬性和方法。如果按照字面意思來理解,那麼prototype就是通過調用建構函式而建立的那個對象執行個體的原型對象。使用原受對象的好處是可以讓所有對象執行個體共用它所包含的屬性和方法。換句話說,不必在建構函式中定義對象執行個體的資訊,而是可以將這些資訊直接添加到原型對象中,如下面的例子所示。

    function Person(){}    Person.prototype.name = 'mychirs';    Person.prototype.age = 29;    Person.prototype.job = 'Software Engineer';    Person.prototype.sayName = function(){      alert(this.name);    };    var person1 = new Person();    person1.sayName();//'mychirs'    var person2 = new Person();    person2.sayName();//'mychirs'    alert(person1.sayName == person2.sayName);//true


在此,我們將sayName()方法和所有屬性直接添加到了Person的prototype屬性中,建構函式變成了空函數。即使如此,也仍然可以通過調用建構函式來建立新對象,而且新對象還會具有相同的屬性和方法。但與建構函式模式不同的是,新對象的這些屬性和方法是由所有執行個體共用的。換句話說.personl和person2訪問的都是同一組屬性和同一個sayName()函數。要理解原型模式的T作原理,必須先理解ECMAScript巾原型對象的性質。


理解原型對象


無論什麼時候,只要建立了一個新函數,就會根據一組特定的規則為該函數建立一個prototype屬性,這個屬性指向函數的原型對象。在預設情況下,所有原型對象都會自動獲得一個constructor(建構函式)屬性,這個屬性包含一個指向prot otype屬性所在函數的指標。就拿前面的例子來說,Person.prototype. constructor措向Person。而通過這個建構函式,我們還可繼續為原型對象添加其他屬性和方法。
建立了自訂的建構函式之後,其原型對象預設只會取得constructor屬性;至於其他方法,則都是從Obj ect繼承而來的。當調用建構函式建立一個新執行個體後,該執行個體的內部將包含—個指標(內部屬性),指向建構函式的原型對象。ECMA-262第5版中管這個指標叫[[Prototype】]。雖然在指令碼中沒有標準的方式訪問【[ Prototype]],但Firefox、Safari和Chrome在每個對象上都支援一個屬性—proto_;而在其他實現中,這個屬性對指令碼則是完全不可見的。不過,要明確的真正重要的一點就是,這個串連存在於執行個體與建構函式的原型對象之間,而不是存在於執行個體與建構函式之間。
以前面使用Person建構函式和Person.prototype建立執行個體的代碼為例,圖6-1展示了各個對象之間的關係。


展示rr Person建構函式、Person的原型屬性以及Person現有的兩個執行個體之間的關係。在此,Person *prototype指向了原型對象,而Person.prototype.constructor叉指回了Person。原型對象中除了包含cons t,ruct or屬性之外,還包括後來添加的其他屬性。Person的每個執行個體personl和person2都包含一個內部屬性,該屬性僅僅指向了Person.prot otype;換句話說,它們與建構函式沒有直接的關係。此外,要格外注意的是,雖然這兩個執行個體都不包含屬性和方法,但我們卻可以調用personl.sayName()。這是通過尋找對象屬性的過程來實現的。
    雖然在所有實現中都無法訪問到[[Prototype]:,但可以通過isProcotypeOf()方法來確定對象之間是否存在這種關係。從本質上講,如果[[ Prototype]]指向調用isPrototypeOf()方法的對象[Person.prototype).那麼這個方法就返回true,如下所示:

alert(Person.prototype.isPrototypeOf(personl));//truealert(Person.prototype.isPrototypeOf(person2));//true

這裡,我們用原型對象的isPrototypeOf()方法測試了personl和person2 0因為它們內部都有一個指向Person.prototype的指標,因此都返回了true。

ECMAScript 5增加了一個新方法,叫Object.getPrototypeOf(),在所有支援的實現中,這個方法返回[[PrototypeJ]]的值。例如:

alert(Object.get PrototypeOf(personl) == Person.prototype);//truealert(Object.get PrototypeOf(personl).name );//'Nicholas'


這裡的第一行代碼只是確定Object.getPrototypeOf()返回的對象實際就是這個對象的原型。第二行代碼取得了原型對象中name屬性的值,也就是‘Nicholas‘。使用Object.getPrototypeOf()可以方便地取得一個對象的原型,而這在利用原型實現繼承(本章稍後會討論)的情況下是非常重要的。支援這個方法的瀏覽器有IE9+、Firefox 3.5+、Safari 5+、Opera 12+和Chrome。
每當代碼讀取某個對象的某個屬性時,都會執行一次搜尋,目標是具有給定名字的屬性。搜尋首先從對象執行個體本身開始。如果在執行個體中找到了具有給定名字的屬性,則返回該屬性的值;如果沒有找到,則繼續搜尋指標指向的原型對象,在原型對象中尋找具有給定名字的屬性。如果在原型對象中找到了這個屬性,則返回該屬性的值。也就是說,在我們調用personl. sayName《)的時候,會先後執行兩次搜尋。首先,解析器會同:“執行個體personl有sayName屬性嗎?”答:“沒有。”然後,它繼續搜尋,再問:“personl的原捌有sayName屬性嗎?”答:“有。”於是,它就讀取那個儲存在原型對象中的函數。當我們調用person2.sayName()時,將會重現相同的搜尋過程,得到相同的結果。而這正是多個對象執行個體共用原型所儲存的屬性和方法的基本原理。


理解js的prototype原型對象

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.