javascript原型Prototype

來源:互聯網
上載者:User

標籤:svg   同名   zoj   moc   hud   icc   xfs   而在   建構函式   

在javaScript建立對象一文中提到過:用建構函式建立對象存在一個問題即同一建構函式的不同執行個體的相同方法是不一樣的,所以我們用原型把建構函式中公用的屬性和方法提取出來進行封裝,達到讓所有執行個體共用的目的。

接下來進一步介紹javaScript原型。

一、javaScript原型機制1、函數與原型的關係

js中建立一個函數,就會自動建立一個prototype屬性,這個屬性指向函數的原型對象,並且原型對象會自動獲得一個constructor(建構函式)屬性,指向該函數。

舉例:以前面的原型模式建立對象為例說明

 View Code

Person對象和Person對象的原型之間的關係如1。

圖1函數、執行個體與原型的關係(圖來著JS高程)

簡單一句話就是:Person.prototype.constructor指向Person,可以在瀏覽器中測試一下。

2、執行個體與原型的關係

通過建構函式建立一個執行個體,該執行個體內部將包含一個屬性(指標),指向建構函式的原型對象。

舉例:Person建構函式的執行個體Person1和Person2的[[Prototype]]屬性都指向Person的原型。1所示。

Note:[[Prototype]]串連是存在於執行個體和建構函式的原型之間,而不是存在執行個體與建構函式之間。

關於這個指標,ECMA-262中叫[[Prototype]],沒有標準的方式訪問[[Prototype]],但Firefox、Safari和Chrome在每個對象上都支援一個屬性__protp__,而在其他實現中,這個屬性對指令碼不可見。

3、原型鏈

執行個體有自己的屬性和方法,而原型封裝了所有執行個體共用的屬性和方法,那這種共用是通過什麼方式實現的呢?答案是原型鏈。

當要訪問執行個體的屬性時,解析器會執行一次搜尋。首先從執行個體對象開始,如果在執行個體中找到了這個屬性,則返回該屬性的值;重點是如果沒有找到的話,則繼續搜尋[[Prototype]]指標指向的原型對象,在原型對象中尋找該屬性,如果找到,則返回該屬性的值。所以通過這種方式多個執行個體就能共用儲存在原型中的屬性和方法。這也是js的原型鏈。

Note:理解了原型鏈,很自然就能明白幾個問題。

a、給執行個體添加一個與原型中同名的屬性,就會將其屏蔽。因為搜尋原型鏈時在執行個體中就能找到然後就返回了,根本到不了原型。

b、可以通過執行個體爬原型鏈訪問原型中的值,但卻不能通過執行個體重寫原型中的值。同理。

c、原型的動態性,在原型上新增屬性或方法能立即從執行個體反應出來。

二、原型相關的方法介紹1、isPrototypeOf()方法

雖然執行個體的[[Prototype]]屬性無法訪問的,我們可以通過isPrototypeOf()方法來確認原型和執行個體之間的關係。這個方法呢是站在原型的角度來檢測原型是不是某個執行個體的原型。A.isPrototypeOf(B),如果A的B的原型返回true,否則返回false。

舉例:因為Person的兩個執行個體lxy和personA內部都有一個[[Prototype]]屬性指向Person.prototype。所以isPrototypeOf方法會返回true。

<script type="text/javascript">    function Person(){    }    Person.prototype.name="lxy";    Person.prototype.age=22;    Person.prototype.job="Software Engineer";    Person.prototype.sayName=function(){        alert(this.name);    }    var lxy=new Person();    var personA=new Person();    console.log(Person.prototype.isPrototypeOf(lxy)); //true    console.log(Person.prototype.isPrototypeOf(personA)); //true</script>
2、Object.getPrototypeOf()方法

這個方法是ECMAScript 5中新增的,返回執行個體的[[Prototype]]值。

這個方法是非常有用的,因為它是在Object上實現的。所以把任何執行個體扔給Object,它都能獲得執行個體的原型。

舉例

<script type="text/javascript">    function Person(){    }    Person.prototype.name="lxy";    Person.prototype.age=22;    Person.prototype.job="Software Engineer";    Person.prototype.sayName=function(){        alert(this.name);    }    var lxy=new Person();    console.log(Object.getPrototypeOf(lxy));    console.log(Object.getPrototypeOf(lxy)==Person.prototype); //true    console.log(Object.getPrototypeOf(lxy).age);//22</script>

結果:

3、hasOwnPrototype()方法

這個方法用於檢測某個屬性是否真正存在於執行個體中。是返回ture,否則返回false。

就像我們自己有一些資源和技能,但是也可以從爹媽那裡得到一些資源和技能,比如看起來你有套別墅,但是你要知道哪些是你真正屬於你自己的,哪些是爹媽給你的。

舉例:比如我一出生父母就給我個名字lxy,這時候我用hasOwnPrototype()方法檢測這個"name"屬性是不真是我的,就會返回false。

後來我自己改了個名字starof,再用hasOwnPrototype()方法檢測,這時就會返回true。

再後來我不想用這個名字了,我就把它delete掉了,用回了我父母給的名字。這時候再用hasOwnPrototype()方法檢測這個"name"屬性是不是我自己的,就會返回false。

這個一波三折的故事代碼如下:

<script type="text/javascript">    function Person(){    }    Person.prototype.name="lxy";    var lxy=new Person();    console.log(lxy.name);    console.log(lxy.hasOwnProperty("name"));  //false     lxy.name="starof";//通過重寫屏蔽原型屬性name,所以這個name就變成了執行個體屬性    console.log(lxy.name);    console.log(lxy.hasOwnProperty("name"));  //true    delete lxy.name;    console.log(lxy.name);    console.log(lxy.hasOwnProperty("name"));  //false</script>
4、in操作符,for-in迴圈,Object的keys()和getOwnPropertyNames()

in操作符在通過對象能夠訪問屬性時返回true,無論該屬性是執行個體屬性還是原型屬性。

for-in迴圈,返回所有能夠通過對象訪問的,可枚舉的屬性。即包括執行個體屬性也包括原型屬性。

屏蔽了原型中不可枚舉的屬性的執行個體屬性也會在for-in迴圈中返回,因為根據規定,所有開發人員定義的屬性都是可枚舉的——只有在IE8及更早版本中例外。

Object.keys()方法,取得執行個體上所有可枚舉的執行個體屬性。該方法接收一個執行個體作為參數,返回一個包含所有可枚舉屬性的字串數組。

Object.getOwnPropertyNames()方法,獲得所有執行個體屬性,無論它是否可枚舉。

 View Code三、原型文法第一種:每添加一個屬性和方法,都直接在原型上加。
<script type="text/javascript">    function Person(){    }    Person.prototype.name="lxy";    Person.prototype.age=22;    Person.prototype.job="Software Engineer";    Person.prototype.sayName=function(){        alert(this.name);    }    var lxy=new Person();</script>
第二種:對象字面量的方法
<script>    function Person(){    }    Person.prototype={        name:"lxy",        age: 22,        job:"Software Engineer",        sayName:function(){            alert(this.name);        }    };    var lxy=new Person();</script>

第二種文法比較簡單,少寫幾行代碼,但是有一點要注意,字面量形式,完全重寫了prototype屬性,所以constructor不再指向Person,而是Object了。

 View Code

如果constructor很重要,可手動設定為Person,如下。

<script>    function Person(){    }    Person.prototype={        constructor:Person,        name:"lxy",        age: 22,        job:"Software Engineer",        sayName:function(){            alert(this.name);        }    };    var lxy=new Person();    console.log(lxy.constructor==Person);//true    console.log(lxy.constructor==Object);//false</script>

 但是這樣寫會導致constructor的[[Enumerable]]特性被置為true。因為開發人員定義的屬性都是可枚舉的。

如果是相容ECMAScript5的JS引擎可使用Object.definePrototype。

 View Code

 

本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載註明出處:http://www.cnblogs.com/starof/p/4904929.html有問題歡迎與我討論,共同進步。

javascript原型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.