xiaochengzi6 / Blog

个人博客
GNU Lesser General Public License v2.1
0 stars 0 forks source link

Babel 编译后的 class 代码是什么样子? #61

Open xiaochengzi6 opened 1 year ago

xiaochengzi6 commented 1 year ago

阅读须知:转换后的代码其实是对class 的一种实现,也能够通过源码去理解 class 为什么有这么多奇怪的规则,如果都清楚可以跳过这个篇 由于源码写的非常清晰了 就不在做多余的注释了具体的可以参考文末文章

在开始看源码之前首先要明白 class 的原理 也就是说要知道它有那些特性这里最关键的有两个地方

  1. class 的类型是 function 但 class 不同于其他的构造函数 它有两条原型链 子类B的 __proto__ 指向继承的class也就是 父类B 第二条原型链子类原型的__proto指向于父类原型的__proto__

这种继承关系类似于寄生组合继承但又有点差异就是它在其基础上增加了一点Object.setPrototypeOf(A, B) 这样的好处是父类的属性(静态属性) 也可以继承到子类上

  1. 明确为什么继承要使用 super 函数 要能清楚的知道 es5 中和 es6 中的继承机制是什么 前者是先创建一个子类实例对象然后去继承父类的属性和方法是 "先实例后继承" es6 是将父类属性和方法加载到一个对象上可以将其理解为 this 对象 (this 是指向的父类的)然后在将这个this 对象作为子类的实例 先继承后实例

es6 中的代码

class Parent {
    constructor(name) {
        this.name = name;
    }
}

class Child extends Parent {
    constructor(name, age) {
        super(name); // 调用父类的 constructor(name)
        this.age = age;
    }
}

var child1 = new Child('kevin', '18');

console.log(child1);

转换后的代码 不过在使用现在版本的 babel 转换的时候可能会得到更多的代码但是原理上都大差不差

'use strict';

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

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

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

var Parent = function Parent(name) {
    _classCallCheck(this, Parent);

    this.name = name;
};

var Child = function(_Parent) {
    _inherits(Child, _Parent);

    function Child(name, age) {
        _classCallCheck(this, Child);

        // 调用父类的 constructor(name)
        var _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name));

        _this.age = age;
        return _this;
    }

    return Child;
}(Parent);

var child1 = new Child('kevin', '18');

console.log(child1);

参考文章:es6 class 转成 es5 后的代码