前面的話
許多的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...