原型鏈的理解

2021-09-12 18:08:03 字數 2850 閱讀 4306

此貼用於記錄原型鏈相關的一些東西。

函式都有prototype,物件都有__proto__,乙個函式的prototype和乙個物件的__proto__就是原型,原型其實也是乙個物件。

乙個函式的prototype和這個函式的示例物件的__proto__是同乙個引用,即:

function a()

let a = new a();

console.log(a.__proto__ === a.prototype); //返回的是true

當呼叫某乙個物件的方法的時候,如果找不到這個物件的方法,則會去找這個物件的原型裡的方法,如果再找不到,則繼續找原型的原型的方法,一直往上找,這個就是原型鏈,如果都找不到,則會報錯。

在引入es6的extends之前,函式的繼承就是通過原型來實現的。下面記錄一下我理解的繼承,下面的繼承參考的是[js繼承的實現方式

][1],他那裡有完整的繼承方法。

function a(name) 

}a.prototype.f2 = function ()

function b(name)

b.prototype = new a('');

let b = new b('test');

b.f1();

b.f2();

console.log(b.__proto__ === b.prototype); //true

console.log(b instanceof a);//true

console.log(b instanceof b);//true

優點:

1.簡單,實現容易

2.能訪問父類所有的方法和屬性

3.例項是當前類的例項,也是父類的例項

缺點:1.要給b的prototype新增方法必須要在 new a('');之後

2.無法實現多繼承

3.沒法向父類的建構函式傳遞引數

function a(name)

}a.prototype.f2 = function()

function b(name)

let b = new b('test');

b.f1();

// b.f2();// 會報錯

console.log(b instanceof a);//false

console.log(b instanceof b);//true

優點:

1.可以使用父類的屬性和方法

2.可以實現多重繼承,即可以call多個函式

3.例項物件是當前類的例項,不是父類的例項

缺點:1.無法獲取a的prototype的屬性和方法

2.只是子類的例項,不是父類的例項

3.無法實現函式復用,每個子類都有父類例項函式的副本,影響效能(此處應該是呼叫call的時候會生成父類的例項副本,具體的還得再研究研究)

function a(name)

}a.prototype.f2 = function()

function b(name)

b.prototype = new a('');

//要修正prototype的constructor,為什麼要修正還有待研究

b.prototype.constructor = b;

let b = new b('test');

b.f1();

b.f2();

console.log(b instanceof a);//true

console.log(b instanceof b);//true

優點:

1.包含了原型鏈繼承和構造繼承的優點

2.解決了原型鏈繼承的無法實現多繼承和沒法向父類的建構函式傳遞引數的缺點

3.解決了構造繼承無法獲取a的prototype的屬性和方法還有只是子類的例項,不是父類的例項的問題

缺點:1.呼叫了兩次父類建構函式,生成了兩份例項(子類例項將子類原型上的那份遮蔽了)

function a(name)

}a.prototype.f2 = function()

function b(name)

(function();

super.prototype = a.prototype;

//將例項作為子類的原型,這樣就可以只獲取a的prototype的屬性了

b.prototype = new super();

//b.prototype.constructor = b;

})();

let b = new b('test');

b.f1();

b.f2();

console.log(b instanceof a);//true

console.log(b instanceof b);//true

優點:

1.在組合繼承的基礎上,只生成了乙份父類的例項,prototype也只繼承了父類的prototype,沒有繼承私有的屬性

缺點:1.實現複雜

順便加乙個知識點,當使用new關鍵字來建立物件的時候,也用到了原型相關的知識,所以也記在了這裡;

假設有乙個function a(name);使用new關鍵字建立乙個a的例項物件let a = new a();

new關鍵字主要做了以下幾個步驟:

(1)建立乙個空的物件

var obj = {};

(2)將這個物件的原型__proto__指向a的prototype

obj.__proto__ = a.prototype

(3)函式a的this指向obj;接著執行a函式

(4將obj返回,變數a指向obj

原型鏈的理解

此貼用於記錄原型鏈相關的一些東西。函式都有prototype,物件都有 proto 乙個函式的prototype和乙個物件的 proto 就是原型,原型其實也是乙個物件。乙個函式的prototype和這個函式的示例物件的 proto 是同乙個引用,即 function a let a new a c...

原型鏈的理解

此貼用於記錄原型鏈相關的一些東西。函式都有prototype,物件都有 proto 乙個函式的prototype和乙個物件的 proto 就是原型,原型其實也是乙個物件。乙個函式的prototype和這個函式的示例物件的 proto 是同乙個引用,即 function a let a new a c...

原型鏈的理解

原型鏈的理解 在理解原型鏈之前,首先要知道建構函式 例項 原型三者是什麼,以及之間的關係。建構函式 function person 例項 var person new person 建構函式 和普通函式沒什麼區別,不過建構函式的首寫字母始終都是大寫的,這是區別於普通函式,它是專門用來建立物件存在的。...