Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Babel.js 如何转化 class #1

Open
gnosis23 opened this issue Oct 3, 2018 · 2 comments
Open

Babel.js 如何转化 class #1

gnosis23 opened this issue Oct 3, 2018 · 2 comments
Labels

Comments

@gnosis23
Copy link
Owner

gnosis23 commented Oct 3, 2018

Babel.js 如何转化 class

Basic Class

源代码来自 Chrome Samples

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }

  sayName() {
    ChromeSamples.log('Hi, I am a ', this.name + '.');
  }

  sayHistory() {
    ChromeSamples.log('"Polygon" is derived from the Greek polus (many) ' +
      'and gonia (angle).');
  }

  static triple(n) {
    n = n || 1;
   	return n * 3;
  }	
}

上面的代码会被转译成:

var Polygon = (function() {
  function Polygon(height, width) {
    _classCallCheck(this, Polygon);

    this.name = "Polygon";
    this.height = height;
    this.width = width;
  }

  _createClass(
    Polygon,
    [{
      key: "sayName",
      value: function sayName() {
        ChromeSamples.log("Hi, I am a ", this.name + ".");
      }
    }, {
      key: "sayHistory",
      value: function sayHistory() {
        ChromeSamples.log(
          '"Polygon" is derived from the Greek polus (many) ' +
            "and gonia (angle)."
        );
      }
    }],
    [{
      key: "triple",
      value: function triple(n) {
        n = n || 1;
        return n * 3;
      }
    }]
  );

  return Polygon;
})();
@gnosis23 gnosis23 changed the title Babel.js class Babel.js 如何转化 class Oct 5, 2018
@gnosis23
Copy link
Owner Author

gnosis23 commented Jul 31, 2019

_createClass

创建基础类

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

以下两件事:

  • 把所有类方法拷贝到 constructor's prototype 里
  • 把所有的 static methods 拷贝到 constuctor 里

注意拷贝的方式为 Object.defineProperty ,并且默认是不能枚举 ( enumerable ) 和可修改的 ( configurable ) 。

继承类

我们的代码如下

class Rectangle extends Polygon {
  constructor(height, width) {
    super(height, width);
    this.name = 'Rectangle';
  }

  sayName() {
    ChromeSamples.log('Sup! My name is ', this.name + '.');
    super.sayHistory();
  }
}

被转化成了下面代码

var Rectangle = (function(_Polygon) {
  _inherits(Rectangle, _Polygon);

  function Rectangle(height, width) {
    _classCallCheck(this, Rectangle);

    var _this = _possibleConstructorReturn(
      this,
      (Rectangle.__proto__ || Object.getPrototypeOf(Rectangle)).call(
        this,
        height,
        width
      )
    );

    _this.name = "Rectangle";
    return _this;
  }

  _createClass(Rectangle, [
    {
      key: "sayName",
      value: function sayName() {
        ChromeSamples.log("Sup! My name is ", this.name + ".");
        _get(
          Rectangle.prototype.__proto__ ||
            Object.getPrototypeOf(Rectangle.prototype),
          "sayHistory",
          this
        ).call(this);
      }
    }
  ]);

  return Rectangle;
})(Polygon);

我们发现 super 好像被翻译成了 (Rectangle.proto || Object.getPrototypeOf(Rectangle))

_inherits

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

注意两点:

  • 设置 subclass 的 prototype 为 Object.create(null) 或者 Object.create(superClass.prototype, { constructor });
  • 设置 subclass 的 [[prototype]] 为 superclass, (为了继承 static methods 和调用 super)。

借用一副图来描述子类和父类之间的关系

subclass

@gnosis23
Copy link
Owner Author

gnosis23 commented Jul 31, 2019

_possibleConstructorReturn

//  var _this = _possibleConstructorReturn(
//       this,
//       (Rectangle.__proto__ || Object.getPrototypeOf(Rectangle)).call(
//         this,
//         height,
//         width
//       )
//   );
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;
}

构造函数有返回值的时候返回,否则返回 this。

_get

// super.sayHistory();
// _get(
//   Rectangle.prototype.__proto__ ||
//     Object.getPrototypeOf(Rectangle.prototype),
//   "sayHistory",
//   this
// ).call(this);
var _get = function get(object, property, receiver) {
  if (object === null) object = Function.prototype; // ??? 1
  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); // ??? 2
  }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant