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