es6 class解析

被咯蘇州發表於2022-04-14

直入主題。原始碼如下:

class A{
  aName = 'A'
  constructor(aAge){
    this.aAge = aAge
  }
  static aStatic = 'aStatic'
}
class B extends A{
  bName = 'b'
  constructor(bAge){
    super()
    this.bAge = bAge
  }
  static bStatic = 'bStatic'
}

var b = new B;

使用babel轉換後的程式碼如下:

"use strict";

// typeof
function _typeof(obj) {}

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 },
  });
  Object.defineProperty(subClass, "prototype", { writable: false });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
// 設定原型 setPrototypeOf
function _setPrototypeOf(o, p) {}

function _createSuper(Derived) {
  var hasNativeReflectConstruct = _isNativeReflectConstruct();
  return function _createSuperInternal() {
    var Super = _getPrototypeOf(Derived),
      result;
    if (hasNativeReflectConstruct) {
      var NewTarget = _getPrototypeOf(this).constructor;
      result = Reflect.construct(Super, arguments, NewTarget);
    } else {
      result = Super.apply(this, arguments);
    }
    return _possibleConstructorReturn(this, result);
  };
}

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  } else if (call !== void 0) {
    throw new TypeError(
      "Derived constructors may only return object or undefined"
    );
  }
  return _assertThisInitialized(self);
}

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

// 是否支援 Reflect.construct
function _isNativeReflectConstruct() {}

// 獲取原型 getPrototypeOf
function _getPrototypeOf(o) {}

// 定義屬性
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);
  }
}
// 給prototype設定屬性 / 設定static屬性 / 禁止修改prototype
function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", { writable: false });
  return Constructor;
}

// 檢查 <不能將類作為函式呼叫>
function _classCallCheck(instance, Constructor) {}

// 設定屬性
function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true,
    });
  } else {
    obj[key] = value;
  }
  return obj;
}

var A = /*#__PURE__*/ _createClass(function A(aAge) {
  _classCallCheck(this, A);

  _defineProperty(this, "aName", "A");

  this.aAge = aAge;
});

_defineProperty(A, "aStatic", "aStatic");

var B = /*#__PURE__*/ (function (_A) {
  _inherits(B, _A);

  var _super = _createSuper(B);

  function B(bAge) {
    var _this;

    _classCallCheck(this, B);

    _this = _super.call(this);

    _defineProperty(_assertThisInitialized(_this), "bName", "b");

    _this.bAge = bAge;
    return _this;
  }

  return _createClass(B);
})(A);

_defineProperty(B, "bStatic", "bStatic");

var b = new B();

流程圖如下:

第一步會執行到這一行:

var A = /*#__PURE__*/ _createClass(function A(aAge) {

進入_createClass, 執行結束後返回處理過的 function A

  1. 給建構函式的原型設定屬性(原型屬性)
  2. 給建構函式本身設定屬性(靜態屬性)
  3. 禁止修改 建構函式的prototype
  4. 最後返回建構函式本身
function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", { writable: false });
  return Constructor;
}

第二步執行:

_defineProperty(A, "aStatic", 'aStatic');

在這裡給A設定aStatic=aStatic.
當key在obj中存在時,修改它的value,並且設定為可列舉,可刪除,可修改
否則在obj中新增value.

// 設定屬性
function _defineProperty(obj, key, value) {
  if (key in obj) {
    // 修改
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true,
    });
  } else {
    // 新增
    obj[key] = value;
  }
  return obj;
}

第三部執行

var B = /*#__PURE__*/ (function (_A) {

這裡實現了原型繼承和方法繼承

_inherits(B, _A);

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, writable: true, configurable: true },
  });

這裡可以拆分成3部分

  1. Object.create(superClass && superClass.prototype);
Object.create()方法建立一個新物件,使用現有的物件來提供新建立的物件的__proto__

也就是說這裡生成了一個空物件{},空物件的__proto__是父類的.prototype.

也就是{}.__proto__ = { constructor: f A() }
  1. { constructor: { value: subClass, writable: true, configurable: true } }
如果該引數被指定且不為 undefined,將為新建立的物件新增指定的屬性值和對應的屬性描述符。

這裡給上面建立的空物件新增constructor屬性,值是f B(),並且設定constructor可修改/刪除,不可被列舉

就變成了這樣{ constructor: f B() }.__proto__ = { constructor: f A() }
  1. subClass.prototype =
這裡給B設定原型

相當於B.prototype = { constructor: f B() }.__proto__ = { constructor: f A() }

到這裡,原型繼承就實現成功了.

Object.defineProperty(subClass, "prototype", { writable: false });

設定B的prototype不可寫

if (superClass) _setPrototypeOf(subClass, superClass);

這裡實現了方法的繼承,B.__proto__ = A

function的寄生組合繼承是沒有上面一步的.只有class extends才有.

var _super = _createSuper(B);

判斷了環境是否支援Reflect.construct,返回_createSuperInternal閉包給_super變數

return _createClass(B);

同上 _createClass A

_defineProperty(B, "bStatic", "bStatic");

同上

第四步執行 new

var b = new B();

先執行 function B(bAge) { 裡面的內容

檢查是否為function _classCallCheck(this, B);

呼叫上面的_super函式, _this = _super.call(this); ,執行 _createSuperInternal

var Super = _getPrototypeOf(Derived),
  result;
if (hasNativeReflectConstruct) {
  var NewTarget = _getPrototypeOf(this).constructor;
  result = Reflect.construct(Super, arguments, NewTarget);
} else {
  result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);

通過 Reflect.construct 或者 Super.apply 得到例項物件.接下來將 this(也就是f B())result 傳遞給 _possibleConstructorReturn

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  } else if (call !== void 0) {
    throw new TypeError(
      "Derived constructors may only return object or undefined"
    );
  }
  return _assertThisInitialized(self);
}
function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError(
      "this hasn't been initialised - super() hasn't been called"
    );
  }
  return self;
}
  1. result有值,並且是object或者function時返回result
  2. result是基本型別時報錯
  3. 否則返回B物件

_defineProperty(_assertThisInitialized(_this), "bName", "b");

給B物件設定class中定義好的屬性_this.bAge = bAge;

執行constructor中的this.bAge = bAge

返回B物件return _this;

相關文章