由es6 class的super引發的思考

前言: 我能理解爲什麼有些人那麼喜歡語言了,或許這就是一種探索發現的魅力吧。一種語言的成型蘊含了它的設計思想。

我們經常遇到這種(mdn截圖):
在這裏插入圖片描述

你也是class,我也是class,憑什麼我繼承了你就不能主宰自己的this。es5沒有這麼說過。
我想這是一種規範,內部肯定做了什麼騷操作,那就一起看一下吧。

es6寫法如下:

class a{}

class b extends a{
	constructor(){
      super()
    	console.log(this)
    }
}

轉碼後的es5代碼如下:


"use strict";

function _typeof(obj) {
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function _typeof(obj) {
      return typeof obj;
    };
  } else {
    _typeof = function _typeof(obj) {
      return obj &&
        typeof Symbol === "function" &&
        obj.constructor === Symbol &&
        obj !== Symbol.prototype
        ? "symbol"
        : typeof obj;
    };
  }
  return _typeof(obj);
}

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  }
  return _assertThisInitialized(self);
}

function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf
    ? Object.getPrototypeOf
    : function _getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
      };
  return _getPrototypeOf(o);
}

function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError(
      "this hasn't been initialised - super() hasn't been called"
    );
  }
  return self;
}

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);
}

function _setPrototypeOf(o, p) {
  _setPrototypeOf =
    Object.setPrototypeOf ||
    function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };
  return _setPrototypeOf(o, p);
}

function _instanceof(left, right) {
  if (
    right != null &&
    typeof Symbol !== "undefined" &&
    right[Symbol.hasInstance]
  ) {
    return !!right[Symbol.hasInstance](left);
  } else {
    return left instanceof right;
  }
}

function _classCallCheck(instance, Constructor) {
  if (!_instanceof(instance, Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

var a = function a() {
  _classCallCheck(this, a);
};

var b =
  /*#__PURE__*/
  (function(_a) {
    _inherits(b, _a);

    function b() {
      var _this;

      _classCallCheck(this, b);

      _this = _possibleConstructorReturn(this, _getPrototypeOf(b).call(this));
      console.log(_assertThisInitialized(_this));
      return _this;
    }

    return b;
  })(a);

轉碼後的代碼聲明瞭一個臨時變量_this並且最終也是返回它,加上super後無非是多了一部操作,即執行了_possibleConstructorReturn這個函數
有位姓李的大佬的說法引起了我的思考,不妨以名字來推斷內容。_possibleConstructorReturn是說constructor可能會返回,我們知道constructor中如果寫了return一個對象,那麼對應的instanceOf將失效,如下:
在這裏插入圖片描述
es5也是如此
es5也是如此
_possibleConstructorReturn函數的第二個參數_getPrototypeOf(b).call(this),調用了父類的構造函數,這一操作更完整的實現了繼承(幫助子類this增添父類構造器中的屬性和方法),當父類的constructor沒有顯式返回一個對象時,_getPrototypeOf(b).call(this)的值是undefined,然而當其顯式返回一個對象時,子類this會被廢棄,_getPrototypeOf(b).call(this)的值是return的值,將轉碼後的代碼進行測試如下:
在這裏插入圖片描述
不加return的效果:

在這裏插入圖片描述
再回到_possibleConstructorReturn這個函數

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  }
  return _assertThisInitialized(self);
}

當第二個參數call,即_getPrototypeOf(b).call(this)是一個對象或者函數時,會直接把它賦值給_this並返回。

constructor的這種顯式return對象的操作影響了this的值,我又特地試了一下es5
在這裏插入圖片描述
父類return並沒什麼用。

所以回到最開始的問題,爲什麼使用this前要加super(),我的理解還是一種規範問題,要繼承就實現最優最完整的繼承,不加的話轉碼的變量_this就沒有initialize,既然super不是默認加上的,那我們就主動加吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章