从babel编译结果分析class的实现原理

Posted on 2021-09-15 14:57  过鹿人  阅读(164)  评论(0编辑  收藏  举报

 

示例:

class A {
    // 属性表达式
    prop1 = 1;
    // get方法
    get value() {
      console.log('Getting the current value!');
      return this.prop1;
    }
    // set方法
    set value(newValue) {
      console.log('Setting the current value!');
      this.prop1 = newValue;
    }
    // 箭头函数表达式
    arrowFunc = (...args) => {
        console.log(args);
    }
    // constructor
    constructor(b = 2) {
        this.prop2 = b;
    }
    // 普通函数表达式
    Func() {
        console.log("Func");
    }
    // 静态属性
    static prop3 = 3;
    // 静态普通函数
    static staticFunc() {
        console.log("staticFunc", this);
    }
    // 静态箭头函数
    static staticArrowFunc = () => {
        console.log("staticArrowFunc", this);
    }
}
const a = new A(3);

使用babel编译成es5的代码,编译结果会生成几个内部函数:

// 类的调用检查,如果调用A不使用new,则会报错
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a 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);
  }
}
// 定义原型上的普通函数、静态普通函数、get和set方法
function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}
// 定义属性到obj上,重新赋值使用defineProperty,第一次赋值直接添加属性
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;
}

类的编译结果:

// A是一个立即执行函数 返回结果是个函数 函数名就是类名
var A = /*#__PURE__*/ (function () {
  // constructor
  function A() {
    // 转化constructor中的默认参数
    var b =
      arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
    // 检查类是否使用new执行
    _classCallCheck(this, A);
    // 属性表达式定义到类实例上
    _defineProperty(this, "prop1", 1);
    // 箭头函数表达式定义到类实例上
    _defineProperty(this, "arrowFunc", function () {
      // 这个for循环是转换...args,遍历arguments,将每一项赋值给args对象
      for (
        var _len = arguments.length, args = new Array(_len), _key = 0;
        _key < _len;
        _key++
      ) {
        args[_key] = arguments[_key];
      }
      console.log(args);
    });
    this.prop2 = b;
  }

  _createClass(
    A,
    [
      {// get和set方法
        key: "value",
        get:
          function get() {
            console.log("Getting the current value!");
            return this.prop1;
          },
        set: function set(newValue) {
          console.log("Setting the current value!");
          this.prop1 = newValue;
        }
      },
      {// 普通函数表达式
        key: "Func",
        value: function Func() {
          console.log("Func");
        }
      }
    ],
    [
      {// 静态普通函数
        key: "staticFunc",
        value: function staticFunc() {
          console.log("staticFunc", this);
        }
      }
    ]
  );

  return A;
})();
// 静态属性定义到类上
_defineProperty(A, "prop3", 3);
// 静态箭头函数定义到类上
_defineProperty(A, "staticArrowFunc", function () {
  console.log("staticArrowFunc", A);
});

var a = new A(3);

下图可描述整个编译结果:

需要注意的是:

  • 类原型上的方法、类的静态方法、类的get和set方法默认是不可枚举的
  • 类实例上的方法和属性、类的静态箭头函数是可枚举的

 

之后再出一章class继承的相关内容

Copyright © 2024 过鹿人
Powered by .NET 8.0 on Kubernetes