談談我對JS原型的理解


昨天阿里實習的第一次電面,也是我人生中的第一次電面,問了很多問題。結果還行吧,算是進入了下一輪。雖然不知道姓名,但還是要感謝面我的那個前輩。好吧,言歸正傳,為什么要寫這篇關於原型的博文呢?因為電面時被問到了。當時有點緊張,感覺回答的很不理想,也許是自己還沒有牢固的掌握吧!所以今天就寫一寫我對原型的理解,順便理一下自己的思路。

首先,JS沒有類繼承機制,它是靠原型機制實現繼承的,兩種方式孰優孰劣,在此不做評判(知識量不足╮(╯▽╰)╭)

先上代碼解釋這一機制:

var people = {
    name: 'xiaoliu'
};

對於JS中所有對象,都有一個內部屬性(供解釋器使用)_proto_,這個屬性指向新建對象的原型,people對象字面量的原型是什么呢,它是Object.prototype。

如圖:

當我們想執行toString()方法時,JS解釋器做了什么呢?首先它會到peope對象里去找,即去找people里的自有屬性,當找到了就去調用該方法,沒找到,就到它_proto_所引用對象里去找,找到了,他就執行原型里的這個方法(子類屬性覆蓋父類屬性)。所以我們說people對象繼承了object.prototype里的方法,但是我更推薦大家這么說Object.prototype是people對象的原型。

下面咱們來做這么一件事:

people.toString = functino(){};

JS解釋器會做什么呢,他還會到原型上找到toString屬性然后賦值么。當然不行,這樣做的話,所有繼承了Object.prototype的對象的toString屬性都會改變。因此賦值時JS解釋器就直接看people對象里的自有屬性有沒有,如果有,改。如果沒,就新建一個屬性賦值。

上代碼證明:

var people = {
    name: 'xiaoliu'
};


console.log(people.hasOwnProperty('toString'));/*賦值前 false*/


people.toString = function(){};


console.log(people.hasOwnProperty('toString'));/*賦值后 true*/

這樣查找屬性和屬性賦值都沒問題了,原型繼承就這么實現了。

不過JS是不允許我們隨意修改對象的原型鏈的,ES5中Object對象上有個getPrototypeOf()方法可以查看原型,但是無法修改。

下面再說說JS怎么初始化新建對象的原型的:

首先, 是對象字面量,上面已經說了,原型初始化成Object.prototype對象。

其次, 是利用對象模板(函數),使用new 運算符創建的對象,它會初始化成為該函數的prototype屬性所指向的對象。

代碼實例:

function People(){
  
  this.name = 'xiaoliu';
}/*對象模板*/

People.prototype = {
constructor: People,/*原來People.prototype指向的對象中默認的唯一不可枚舉屬性,現在修改了prototype的引用,所以最好再恢復一下*/
toString: function(){return this.name}
};/*修改原型*/
var people = new People();/*創建對象*/ people.toString();/*執行繼承方法*/

最后,是通過ES5提供的Object.create()方法

代碼實例:

var people = {name: 'xiaoliu'};

var a = Object.create(people);/*創建一個新對象,並把原型_proto_初始化為people對象*/

a.name;/*返回原型鏈上的name屬性*/

好吧,先到此為止吧,以后有機會再談談this。

如有錯誤,歡迎指正^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM