參考文章es6
babel是一個es6->es5的編譯器, 它能夠將es6的代碼轉換成等價的es5.express
咱們看看它是怎麼模擬super
關鍵字的.babel
class A{ constructor(){ } render(){ console.log(1) } } class B extends A{ constructor(){ super(); } render(){ super.render(); console.log(2); } }
與上面es6等價的es5語句以下函數
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } // 貌似不支持多重繼承啊. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } // 覆寫子類的prototype對象 subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); // 設置隱式原型, 感受這樣很怪. 由於這樣意爲着子類將成爲父類的實例對象...呃, 相似的概念 // 但我不以爲父子類關係與類和實例的關係同樣... if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var A = function () { function A() { // 檢查當前this對象是否爲A的實例, 若是不是說明是當成函數直接用的... _classCallCheck(this, A); } // 建立類屬性 _createClass(A, [{ key: "render", value: function render() { console.log(1); } }]); return A; }(); var B = function (_A) { _inherits(B, _A); function B() { _classCallCheck(this, B); return _possibleConstructorReturn(this, (B.__proto__ || Object.getPrototypeOf(B)).call(this)); } // 原型方法中取到了構造函數類自己, 感受這樣耦合性比較大 // 這是直接到`B.prototype.__proto__`指向的原型鏈上尋找目標方法, // 但我不想每次在寫子類方法時還要顯示寫父類變量. _createClass(B, [{ key: "render", value: function render() { _get(B.prototype.__proto__ || Object.getPrototypeOf(B.prototype), "render", this).call(this); console.log(2); } }]); return B; }(A);
但這種轉換並非我想要的那種, 由於它的super
實現其實是在子類方法中經過顯式調用父類名.父類方法
的形式完成的, 做爲編譯結果, 它能夠隱藏實際代碼編寫時的耦合性, 但直接寫es5的語法時, 顯示指定要調用的父類名稱依然不能說是一種好的解決方案.this