js 理解繼承

Js裏的繼承通常就是原型鏈繼承。即實現A的原型的原型爲B的原型,則A繼承B。
首先須要瞭解下實例,構造函數,原型對象之間是怎樣的關係。實例爲從構造函數new獲得的新對象,它有__proto__能夠指向原型對象,經過instanceof方法能夠判斷實例的構造函數類型;構造函數的prototype指向原型對象,原型對象有constructor指向構造函數。詳細瞭解能夠參考http://www.javashuo.com/article/p-pgcjftwn-gr.htmlsegmentfault

瞭解了三者關係以後,咱們須要作的其實就是更改A的原型。讓新的原型知足兩個條件:函數

  1. 新原型的原型指向被繼承者B
  2. 新原型的構造函數指向A
function A() {
}
function B() {
}
B.prototype.say = function(){console.log('say')}

// 準備一箇中間變量
function C(){}
// 從新設置C的原型爲B的原型
C.prototype = B.prototype
// 建立一個實例c,此時c的原型是B的原型
var c = new C()
// 設置實例c的構造函數指向A,
c.constructor = A

// 上述步驟後A新的原型對象c建立完成,它的原型指向B,構造函數指向A
A.prototype = c
// 此時原型鏈爲 new A()._proto__ (c) => B.prototype => Object.prototype => null
console.log(new A(), new B())

image.png

有的人可能會奇怪,爲何不能直接使用A.prototype = B.prototype,這樣的話至關於A,B共用一個原型對象,A在原型的更改會直接影響B,不符合繼承要求,子類沒法獨自擴展;並且,A的原型對象的構造函數此時指向的是B,意味着實例沒法從新訪問構造函數。spa

function A() {
}
function B() {
}
B.prototype.say = function(){console.log('say')}
A.prototype = B.prototype
A.prototype.sayA = function(){console.log('sayA')}
console.log(new B().sayA()) // sayA
console.log(new A().__proto__.constructor) // function B() {}

常見的介紹js繼承的文章有不少,裏面通常介紹了諸如原型繼承,構造函數繼承,組合繼承等等,以及不一樣方式的缺點與優勢,看的懵懵的,但咱們只要知道這些方式的本質就是建立原型鏈(A的原型的原型爲B的原型),那些方法其實就很好理解了。要作到繼承直接使用A.prototype.__proto__ = B.prototype 或者Object.setPrototypeOf(A.prototype, B.prototype)也徹底能夠,可是要注意是否支持。詳細瞭解參考MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOfprototype

相關文章
相關標籤/搜索