Js裏的繼承通常就是原型鏈繼承。即實現A的原型的原型爲B的原型,則A繼承B。
首先須要瞭解下實例,構造函數,原型對象之間是怎樣的關係。實例爲從構造函數new獲得的新對象,它有__proto__能夠指向原型對象,經過instanceof方法能夠判斷實例的構造函數類型;構造函數的prototype指向原型對象,原型對象有constructor指向構造函數。詳細瞭解能夠參考http://www.javashuo.com/article/p-pgcjftwn-gr.htmlsegmentfault
瞭解了三者關係以後,咱們須要作的其實就是更改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())
有的人可能會奇怪,爲何不能直接使用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