ES6 转 ES5 babel 源码阅读篇(一)

 一、先吃个小栗子

 

class Person {

}

使用 class 定义的 Person 类,经过 Babel转化为 ES5 生成的代码如下 

"use strict";

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

var Person = function Person() {
    // 检查当前 this 实例是不是 Person 创建出来的
    _classCallCheck(this, Person); // 目的:区别普通函数
};

可以看到 class 定义的 Person类,在es5 中是使用 function 来定义的,里面调用了_classCallCheck(this, person) 。这个方法的目的是:把 Person这个函数和普通函数区别开来,主要是希望通过 new 去调用,而不是随随便便调用,如下

如果当前一个普通函数调用,可以看到在严格模式下 this 是 undefined,,非严格模式下是 window,于是会判断 undefined或者 window 并不能作为 Person 的实例,因此会报错。

二、再吃个中栗子

class Person {
    constructor (name, age) {
        this.name = name 
        this.age = age
    }

    eating() {
        console.log(this.name + ' 在吃栗子')
    }
}

经过 Babel 转化并美化代码如下:这次东西比较多,不要被吓到,我们一步步来

"use strict";

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

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}

var Person = /*#__PURE__*/ (function () {
  function Person(name, age) {
    _classCallCheck(this, Person);

    this.name = name;
    this.age = age;
  }

  _createClass(Person, [
    {
      key: "eating",
      value: function eating() {
        console.log(this.name + " 在吃栗子");
      }
    }
  ]);

  return Person;
})();

 首先用了一个立即执行函数,把 function 定义的 Person 类放在立即执行函数中,最后并返回了。这里为什么要用到立即执行函数?

  1. 防止全局变量名冲突,这个没什么好说的,以前用立即执行函数实现模块化的道理
  2. 在立即执行函数上面加了一个魔法注释 /*#__PURE__*/,后面在进行代码优化压缩的时候碰到这个标记,知道这个函数是个纯函数没有产生任何可见的副作用,在进行 webpack压缩的时候会进行 tree-shaking,如果没有用到的话就会直接删掉,最后压缩的包体积就会小很多

立即执行函数里面放的是一个 function 实现的Person类,以及类中的方法_classCallCheck这个前面讲过,然后下面执行了 _createClass(Person, [{ ... }]) ,这个方法的目的又是什么呢?

在 es6以前,给类添加公共方法,是在原型上添加的 

Person.prototype.running = function () {
    console.log(this.name + ' 在跑步')
}

因此 _createClass() 这个方法的作用是往Person的原型上添加方法,第一个参数是类,第二个参数接受一个数组,数组里面存放着描述方法的对象们,

  _createClass(Person, [
    {
      key: "eating",
      value: function eating() {
        console.log(this.name + " 在吃栗子");
      }
    },
    {
      key: "running",
      value: function running() {
        console.log(this.name + " 在跑步")
      }
    }
  ]);

那为什么不直接在 Person 的原型上直接加而是搞一个方法添加,这就是提高代码的复用,真实开发中,我不可能直接Person一个类 

_createClass 方法

  1. 首先判断第二个参数有没有值,如果有值,把Person的原型对象 和 描述方法的对象数组传递进_defineProperties,然后调用,遍历数组取到每个属性,然后设置可枚举属性和可配置属性,判断是否有值,来设置是否可写。最后通过 Object.defineProperty 往原型上设置方法
  2. 其次判断有没有静态方法,有就直接把静态方法定义到Person上面
  3. 返回Person对象

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值