原型鏈繼承 與 instanceof原理

2021-09-25 16:13:35 字數 4121 閱讀 8158

前面的話

許多的oo語言都支援兩種繼承方式:介面繼承與實現繼承。介面繼承只繼承方法簽名,而實現繼承則繼承實際的方法。js只支援實現繼承,而且其實現繼承主要是依靠原型鏈來實現的。

原型鏈繼承的本質

原型鏈繼承的本質是重寫原型物件,代之是乙個新型別的例項.

下列**中,fn的新原型不僅有new fn1()例項上的全部屬性和方法,並且還繼承了fn1原型上的屬性與方法。

function fn1() 

fn1.prototype.getfn1vlaue = function ()

function fn2()

fn2.prototype = new fn1();// fn1 的例項為fn2的原型

fn2.prototype.getfn2value = function ()

var instance = new fn2();// 建立fn2的例項

instance例項可以訪問fn1中的屬性,原因就是因為fn2繼承了fn1,而繼承是通過建立fn1例項實現的。

fn2的原型物件包含fn1例項的所以屬性和方法,然後在fn2的原型物件上又新增了乙個getfn2value方法。

instance是fn2的例項,所以instance.__proto__與fn2.prototype返回的物件一樣。

instance. __ proto __.__proto__理所當然返回的就是fn1.prototype。因為fn2.prototype被重寫了為fn1,所以fn2.prototype.constructor === fn1,相應的instance.constructor指向fn1。

說明:instance.getfn1vlaue()會經歷三個步驟:1) 搜尋例項 2)fn2.prototype 3)fn1.prototype。在第三步找到這個方法。

instanceof 操作符原理

instanceof操作符用來檢測 例項與原型鏈**現過的建構函式,結果返回true。

上面的例子

instanceof原理就是沿著原型鏈上一層一層查詢,只要instance.[proto…] === instance.constructor.prototype,那麼instance instanceof constructor就返回true。

還有一種方法是使用原型物件上的isprototypeof()方法,原理一樣:

console.log( fn2.prototype.isprototypeof(instance));

console.log( fn1.prototype.isprototypeof(instance));

console.log( object.prototype.isprototypeof(instance));

原型鏈繼承的問題

[問題 1]

function fn1() 

fn1.prototype.getcolors = function ()

function fn2()

fn2.prototype = new fn1();// 繼承了fn1

建構函式fn1中定義了乙個colors屬性,該屬性包含乙個陣列(引用型別)。將fn1的例項賦給fn2.prototype,那麼fn1的例項屬性colors就變成了fn2.prototype的屬性,又因為原型屬性上的引用型別會被所有例項共享,所以多個例項對引用型別的操作會被篡改。

[問題 2]

子型別原型的上的額constructor屬性被重寫了,執行了fn2.prototype = new fn1()後原型被重寫.

console.log(fn2.prototype.constructor === fn1);// true
解決方法就是重寫fn2.prototype.constructor屬性,指向自己的建構函式fn2

fn2.prototype = new fn1();

fn2.prototype.constructor = fn2;

[問題 3]給子型別原型新增屬性和方法必須在替換原型之後,原因就是因為在fn2.prototype = new fn1()之後fn2.prototype會被覆蓋

function fn1() 

fn1.prototype.getvalue= function ()

function fn2()

fn2.prototype = new fn1();// 繼承了fn1

fn2.prototype.constructor = fn2;

// 重寫了超型別的getvalue方法

前面說過instance.getvalue()會經過三個步驟:1) 搜尋例項 2)搜尋fn2.prototype 3)搜尋fn1.prototype,所以結果為「xiaoqi」。但是如果想用fn1.prototype上的getvalue方法,使用fn1的例項呼叫getvalue方法就可以了。

[注意]:在fn2.prototype = new fn1()之後,想為fn2.prototype新增新的屬性或方法,不能使用物件字面量的方式 新增,這樣會重寫原型鏈。

function fn1() 

fn1.prototype.getcolors= function ()

function fn2()

fn2.prototype = new fn1();// 繼承了fn1

// 使用物件字面量新增新的方法,會導致上面的**無效。

fn2.prototype =

}var instance = new fn2();

instance.getcolors();

上面的**剛剛把fn1的例項覆給fn2.prototype,緊接著又將原型替換為乙個物件字面量,導致原型被重寫, fn1 與 fn2之間沒有了關係。

原型 原型鏈與繼承

面試中經常考到物件導向的一些知識,在這記錄一下,如有不對歡迎指正,願在前端的道路上共勉!一 原型 1.什麼是原型 簡單說就像css的class一樣,是公用的,給dom元素加個class名就可以公用樣式,那麼原型就相當於css裡面的class,都可以用。在建構函式建立出來的時候,系統會預設的幫建構函式...

原型鏈與繼承

一 原型鏈 基本思想 讓乙個引用型別繼承另乙個引用型別的屬性和方法。建構函式 原型 例項的關係 每個建構函式都有乙個原型物件,原型物件都包含乙個指向建構函式的指標,而例項都包含乙個指向原型物件內部的指標。原型鏈繼承例項 function supertype this.property true su...

原型 原型鏈 繼承

原型 是function物件的乙個屬性,它定義了建構函式 製造出的物件 的公共祖先。通過該建構函式產生的物件,可以繼承該原型的屬性和方法。原型也是物件 這定義有點模糊,用 解釋一下 我們在控制台中列印出了這個,首先son物件的建構函式是foo,但是我們的foo中什麼屬性都沒有,怎麼會出現乙個 pro...