談到繼承,或者更廣義上的:一個物件可以使用另外一個物件的屬性或方法。實現起來無外乎有兩種方式:
apply or call 改變this的作用域
原型繼承 改變__proto__指向,新增作用域鏈
而JavaScript所有的繼承實現,都是圍繞以上兩點展開的。
1.原型鏈繼承
2.建構函式繼承
3.組合繼承
4.ES6 extends 繼承
原型鏈繼承
function Father(){}
function Son(){}
Son.prototype = new Father()
缺點很明顯:
子類建構函式不能傳遞引數
子類只是拷貝父類的引用,父類的引用型別的屬性會被所有的子類共享
建構函式繼承
function Father(){}
function Son(){
Father.apply(this, arguments)
}
解決了引數和引用共享問題,但是父類方法不能夠共享。
組合繼承
function Father(){}
function Son(){
Father.apply(this, arguments)
}
Son.prototype = new Father()
實現了屬性分離,方法共享;es5下的完美
繼承方案
ES6繼承
我們的主角,ES6 extends,就是對組合繼承的改進。不同的是在子類中,子類作用域和父類作用域誰先誰後的問題。
在ES5中,首先宣告子類的 作用域,然後在將子類的作用域指向父類
在ES6中,是首先將子類的作用域指向父類,然後在此基礎上增強子類的作用域。這也是為什麼在子類建構函式中一定要顯示呼叫super()的原因。
參考babel轉換後的程式碼:
var Son = function (_Father) {
_inherits(Son, _Person);
function Son() {
_classCallCheck(this, Son);
//為了方便閱讀,簡略了程式碼
var _this = _possibleConstructorReturn(this,Father.call(this));
_this.gender = "male";
return _this;//返回的是 指向父類的作用域 _this
}
return Son;
}(Father);
關於更詳細的ES6 Class的實現機制,可以參考我的另外一篇文章:聊一聊ES6 CLASS 實現原理<>
後記
第一次在sifou
上釋出文章,新增了一個專題——Javascript五十問——裡面會細緻聊一些關於JavaScript原生和ES6的內容;算是我自己在開發過程中的一點積累;如果哪位發現錯誤,希望不吝賜教,共同進步!
參考文件
一篇文章理解JS繼承 https://segmentfault.com/a/11…
Javascript 紅寶書
阮一峰 ES6標準入門