Skip to content

扩展-babel 对类的转换

我们直接看源代码,写了一个类,然后在 babel 官网在线进行转换,分析转换结果。

js
class A {
  prop1 = 1;

  method2 = (...args) => {
    console.log(args);
  };

  constructor(b = 2) {
    this.prop2 = b;
  }

  method1() {
    console.log("method1");
  }

  static method3() {
    console.log("method3", this);
  }

  static method4 = () => {
    console.log("method4", this);
  };
}
js
"use strict";

function _instanceof(left, right) {
  //ES6的判断实例方式,因为ES6必须是使用new来创建实例。
  //每一个class都有一个Symbol.hasInstance函数,用来判断是否有实例
  if (
    right != null &&
    typeof Symbol !== "undefined" &&
    right[Symbol.hasInstance]
  ) {
    return !!right[Symbol.hasInstance](left);
  } else {
    //es6的判断实例方法
    return left instanceof right;
  }
}

function _classCallCheck(instance, Constructor) {
  //判断instance 是不是Constructor的实例
  if (!_instanceof(instance, Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

//props: [{key:"xxx", value:"xxxxxx"}, {key:"ccc", value: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;
    //这段函数最重要的就是这句话,以上的都是在构造descriptor描述符。
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return 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 =
  //该立即执行函数的返回结果,应该是一个构造函数A
  (function () {
    //构造函数A,对应类中的constructor
    function A() {
      //转换:构造函数的参数默认值
      var b =
        arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
      //类调用检查
      _classCallCheck(this, A);
      //定义一个属性:给this定义一个属性prop1,赋值为1,类似于 this.prop1 = 1;
      _defineProperty(this, "prop1", 1);
      //将箭头函数方法,作为普通属性定义,箭头函数方法并不在原型上
      //这个函数是为了处理剩余参数,本质就是将argumets伪数组转换为真数组
      _defineProperty(this, "method2", function () {
        for (
          var _len = arguments.length, args = new Array(_len), _key = 0;
          _key < _len;
          _key++
        ) {
          args[_key] = arguments[_key];
        }

        console.log(args);
      });

      this.prop2 = b;
    }

    //为构造函数A,定义原型方法,以及静态方法
    _createClass(
      A,
      [
        {
          key: "method1",
          value: function method1() {
            console.log("method1");
          },
        },
      ],
      [
        {
          key: "method3",
          value: function method3() {
            console.log("method3", this);
          },
        },
      ]
    );

    return A;
  })();

_defineProperty(A, "method4", function () {
  console.log("method4", A);
});

心得

  • 读代码的时候应当先找准关键点,从关键点入手,先读整体,然后再读细节。把握整体思想步骤,再深入到每一个函数的细节中去。抽丝剥茧。

  • ES6 中的 class 必须使用 new 来创建实例,且每一个 class 都有一个 Symbol.hasInstance()函数

  • 箭头函数实际上属于类的属性,而不是原型上的方法。

MIT License