您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關 ES5 與 ES6 中繼承行為的區別有哪些,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
ES5 中的繼承
// Shape - 父類(superclass) function Shape() { this.x = 0; this.y = 0; } // 父類的方法 Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info('Shape moved.'); }; // Rectangle - 子類(subclass) function Rectangle() { Shape.call(this); // call super constructor. } // 子類續承父類 Rectangle.prototype = Object.create(Shape.prototype); Rectangle.prototype.constructor = Rectangle; var rect = new Rectangle(); console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true console.log('Is rect an instance of Shape?', rect instanceof Shape); // true rect.move(1, 1); // Outputs, 'Shape moved.'
如上所示: 展示了一個 ES5 中實現單繼承的例子,在《Javascript 高級程序設計》一書中,給這種繼承方式定義為「寄生組合式繼承」。不管什么形式,什么命名,在 ES5 中實現繼承始終就是要堅持一個原則:將實例屬性放在構造函數中掛在this上,將一些方法屬性掛在原型對象上,子類可共享。 上面這種繼承方式的關鍵在于兩點:
子類構造函數通過 apply 或者 call 的方式運行父類的構造函數,此舉將父類的實例屬性掛在子類的 this 對象上
以父類的原型對象為基礎,與子類的原型對象之間建立原型鏈關系,使用了 Object.create,本質在于 Child.prototype.__proto === Parent.prototype;
ES6 中的繼承
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 調用父類的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); } }
ES6 中的繼承使用到了 extends 關鍵字,function 也變成了 class 關鍵字。class 的本質還是一個語法糖,這個大家都會脫口而出,但是在繼承機制這里到底是如何做到的,我們看一下 babel 在此處是如何幫我們轉譯的,
var ColorPoint = /*#__PURE__*/ function (_Point) { _inherits(ColorPoint, _Point); function ColorPoint(x, y, color) { var _this; _classCallCheck(this, ColorPoint); _this = _possibleConstructorReturn(this, _getPrototypeOf(ColorPoint).call(this, x, y)); // 調用父類的constructor(x, y) _this.color = color; return _this; } _createClass(ColorPoint, [{ key: "toString", value: function toString() { return this.color + ' ' + _get(_getPrototypeOf(ColorPoint.prototype), "toString", this).call(this); } }]); return ColorPoint; }(Point);
如上是經過babel轉譯后的代碼,有幾個關鍵點:
一、 _inherits()
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
首先完成extends對象的校驗,必須是function 或者null,否則報錯。其次完成以下事情:
ColorPoint.__proto__ === Point; ColorPoint.prototype.__proto__ === Point.prototype;
二、 ColorPoint 構造函數中 _classCallCheck(), _possibleConstructorReturn()
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
主要是用來檢測構造函數不能直接調用,必須是通過new的方式來調用。
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
調用父類的構造函數,初始化一些實例屬性,并將this返回。使用該返回的this賦值給子類的this對象,子類通過這一步返回的this對象,再該基礎之上在添加一些實例屬性。
這就是最大的不同之處。如果不經歷這一步,子類沒有this對象,一旦操作一個不存在的this對象就會報錯。
三、 _createClass()
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
關于 ES5 與 ES6 中繼承行為的區別有哪些就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。