一、概要
- 本文主要介紹了原型鏈的相關知識
- 建立對象的方法
- 原型、構造函數、實例、原型鏈的關係
- instanceof的原理
- new運算符
二、建立對象的方法
// 建立對象的方式
// (1) 字面量
var obj1 = { name: 'obj1' };
var obj2 = new Object({ name: 'obj2' }); // 不是字面量,但結果和字面量等同
// (2) 構造函數
var Fn = function(name) {
this.name = name;
}
var obj3 = new Fn('obj3');
// (3) Object.create
var parentObj = { name: 'obj4'};
var obj4 = Object.create(parentObj);
複製代碼
三、原型、構造函數、實例、原型鏈
// 原型、構造函數、實例、原型鏈的關係
// 一、實例 ==> 1. 對象就是一個實例,就有_proto_屬性
// 2. 實例經過_proto_原型鏈找到prototype原型對象,prototype原型對象的屬性被全部實例共享。
// 二、構造函數 ==> 1.能夠經過new運算符生成一個實例。
// 2.任何函數均可以做爲構造函數。
// 3.只要被new運算符使用過的函數就是一個構造函數
// 三、原型 ==> 1. 函數都有prototype屬性,prototype屬性的值就是一個初始化的原型對象。
// 2. 原型對象有個constructor和_proto_屬性,constructor是一個構造函數。
// 3. Fn.prototype.constructor === Fn // constructor函數指向構造函數自己。經過constructor把原型對象和構造函數關聯。
// 四、原型鏈 ==>1. 對象有_proto_屬性(函數也是對象,因此函數也有_proto_屬性)
// 2. 實例經過_proto_原型鏈找到prototype原型對象,若是找不到,則經過原型對象的_proto_繼續往上找,一直到頂層。
// 五、關係:==> 1. Fn.prototype.constructor === Fn // 構造函數原型的constructor屬性指向構造函數自己
// 2. obj3.__proto__.constructor === Fn
// 3. obj3.__proto__.constructor === Fn.prototype.constructor
// 4. obj3.__proto__ === Fn.prototype // 修改prototype的屬性, __proto__也會修改,同理也是
複製代碼
四、instanceof的原理
// instanceof ==> 1. 判斷實例對象的__proto__和構造函數的prototype屬性指向同一個引用地址
(並不能判斷一個對象是否是一個構造函數直接生成的實例),
// 2. obj3 instanceof Fn // true
// 3. obj3 instanceof Object // true,因爲 Fn instanceof Object === true
// 4. 如何準確判斷一個對象是否是一個構造函數直接生成的實例對象(經過constructor):
// obj3.__proto__.constructor === Fn.prototype.constructor // true
// obj3.__proto__.constructor === Object.prototype.constructor // false
複製代碼
五、new運算符
var obj3 = new Fn('obj3');
obj3實例對象在建立過程
1. new運算符會先建立一個新對象,它繼承自Fn.prototype。
2. 構造函數Fn被執行,相應的參數會被傳入,this會被指向這個新的實例。
3. 在不傳參數時,new Fn等同於new Fn()
4. 若是Fn返回了一個對象,那麼這個對象會取代new出來的對象。
5. 若是構造函數沒有返回對象,那麼new出來的對象就是最終的結果。
new運算符的工做原理,用代碼模擬
var newTest = function(fn) {
var initObj = Object.create(fn.prototype);
var obj = fn.call(initObj);
if(typeof obj === 'object') {
return obj;
} else {
return initObj;
}
}
var Fn = function() {
// this.name = 'obj3', 最後newTest(Fn)返回的結果徹底等同。
return {
name: 'obj3';
}
}
newTest(Fn)
複製代碼
6. 總結
- 本身也是在處在深刻學習和理解的階段,若有錯誤之處,請指正。
- 後續爲將繼續分享繼承以及面向對象的相關內容。
- 未完待續。