原型、構造函數、實例、原型鏈的關係

一、概要

  • 本文主要介紹了原型鏈的相關知識
  • 建立對象的方法
  • 原型、構造函數、實例、原型鏈的關係
  • 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. 總結

  1. 本身也是在處在深刻學習和理解的階段,若有錯誤之處,請指正。
  2. 後續爲將繼續分享繼承以及面向對象的相關內容。
  3. 未完待續。
相關文章
相關標籤/搜索