Home  >  Article  >  Web Front-end  >  How to convert babel to es6

How to convert babel to es6

php中世界最好的语言
php中世界最好的语言Original
2018-06-11 15:15:171564browse

This time I will show you how to convert babel to es6, and what are the precautions for converting babel to es6. The following is a practical case, let's take a look. z

babel is a transcoder, which is currently used to develop react and vue projects. It can convert es6 syntax to es5, as well as JSX and other syntax.

In our projects, we all convert specific codes, such as env, stage-0, etc., by configuring plug-ins and presets (a collection of multiple plug-ins).

In fact, Babel can convert any code through custom plug-ins. Next, let’s learn about Babel through an example of “converting es6’s class to es5”.

The content is as follows:

webpack environment configuration

Everyone should have configured the babel-core loader and its role It provides the core API of Babel. In fact, our code conversion is implemented through plug-ins.

Next, we will implement an es6 class conversion plug-in ourselves without using third-party plug-ins. First perform the following steps to initialize a project:

  1. npm install webpack webpack-cli babel-core -D

  2. Create a new webpack.config.js

  3. Configure webpack.config.js

If our plug-in name wants to be called transform-class, we need to make the following configuration in the webpack configuration:

Next we create a new folder of babel-plugin-transform-class in node_modules to write the logic of the plug-in (if it is a real project, you need to write this plug-in and Publish to npm warehouse), as shown below:

The red area is my newly created folder, and above it is a standard plug-in project structure. For convenience, I just write The core index.js file.

How to write a babel plug-in

The babel plug-in is actually implemented through AST (Abstract Syntax Tree).

babel helps us convert js code into AST, then allows us to modify it, and finally convert it into js code.

So there are two questions involved: What is the mapping relationship between js code and AST? How to replace or add a new AST?

Okay, let’s first introduce a tool: astexplorer.net:

This tool can convert a piece of code into AST:

As shown in the figure , we wrote an es6 class, and then the right side of the webpage generated an AST for us, which actually turned each line of code into an object, so that we implemented a mapping.

Introducing another document: babel-types:

This is the API document for creating AST nodes.

For example, if we want to create a class, we first convert it in astexplorer.net and find that the AST type corresponding to the class is ClassDeclaration. Okay, let’s search in the documentation and find that just calling the following api is enough:

The same goes for creating other statements. With the above two things, we can No conversions were made.

Now we start to actually write a plug-in, which is divided into the following steps:

  1. Export a function in index.js

  2. The function returns an object, and the object has a visitor parameter (must be called visitor)

  3. Query the class through astexplorer.net and the corresponding AST node is ClassDeclaration

  4. Set a capture function in vistorClassDeclaration, which means I want to capture all ClassDeclaration nodes# in the js code

  5. ##Write logic code and complete the conversion

  6. module.exports = function ({ types: t }) {
     return {
      visitor: {
       ClassDeclaration(path) {
        //在这里完成转换
       }
      }
     };
    }
There are two parameters in the code, the first one

{types:t} The thing is to deconstruct the variable t from the parameters, which is actually t in the babel-types document (red box in the picture below), which is used to create nodes:

第二个参数 path ,它是捕获到的节点对应的信息,我们可以通过 path.node 获得这个节点的AST,在这个基础上进行修改就能完成了我们的目标。

如何把es6的class转换为es5的类

上面都是预备工作,真正的逻辑从现在才开始,我们先考虑两个问题:

我们要做如下转换,首先把es6的类,转换为es5的类写法(也就是普通函数),我们观察到,很多代码是可以复用的,包括函数名字、函数内部的代码块等。

 

如果不定义class中的 constructor 方法,JavaScript引擎会自动为它添加一个空的 constructor() 方法,这需要我们做兼容处理。

接下来我们开始写代码,思路是:

  1. 拿到老的AST节点

  2. 创建一个数组用来盛放新的AST节点(虽然原class只是一个节点,但是替换后它会被若干个函数节点取代) 初始化默认的 constructor 节点(上文提到,class中有可能没有定义constructor)

  3. 循环老节点的AST对象(会循环出若干个函数节点)

  4. 判断函数的类型是不是 constructor ,如果是,通过取到数据创建一个普通函数节点,并更新默认 constructor 节点

  5. 处理其余不是 constructor 的节点,通过数据创建 prototype 类型的函数,并放到 es5Fns

  6. 循环结束,把 constructor 节点也放到 es5Fns

  7. 判断es5Fns的长度是否大于1,如果大于1使用 replaceWithMultiple 这个API更新AST

module.exports = function ({ types: t }) {
 return {
  visitor: {
   ClassDeclaration(path) {
    //拿到老的AST节点
    let node = path.node
    let className = node.id.name
    let classInner = node.body.body
    //创建一个数组用来成盛放新生成AST
    let es5Fns = []
    //初始化默认的constructor节点
    let newConstructorId = t.identifier(className)
    let constructorFn = t.functionDeclaration(newConstructorId, [t.identifier('')], t.blockStatement([]), false, false)
    //循环老节点的AST对象
    for (let i = 0; i < classInner.length; i++) {
     let item = classInner[i]
     //判断函数的类型是不是constructor
     if (item.kind == &#39;constructor&#39;) {
      let constructorParams = item.params.length ? item.params[0].name : []
      let newConstructorParams = t.identifier(constructorParams)
      let constructorBody = classInner[i].body
      constructorFn = t.functionDeclaration(newConstructorId, [newConstructorParams], constructorBody, false, false)
     } 
     //处理其余不是constructor的节点
     else {
      let protoTypeObj = t.memberExpression(t.identifier(className), t.identifier(&#39;prototype&#39;), false)
      let left = t.memberExpression(protoTypeObj, t.identifier(item.key.name), false)
      //定义等号右边
      let prototypeParams = classInner[i].params.length ? classInner[i].params[i].name : []
      let newPrototypeParams = t.identifier(prototypeParams)
      let prototypeBody = classInner[i].body
      let right = t.functionExpression(null, [newPrototypeParams], prototypeBody, false, false)
      let protoTypeExpression = t.assignmentExpression("=", left, right)
      es5Fns.push(protoTypeExpression)
     }

    }
    //循环结束,把constructor节点也放到es5Fns中
    es5Fns.push(constructorFn)
    //判断es5Fns的长度是否大于1
    if (es5Fns.length > 1) {
     path.replaceWithMultiple(es5Fns)
    } else {
     path.replaceWith(constructorFn)
    }
   }
  }
 };
}

优化继承

其实,类还涉及到继承,思路也不复杂,就是判断AST中没有 superClass 属性,如果有的话,我们需要多添加一行代码 Bird.prototype = Object.create(Parent) ,当然别忘了处理 super 关键字。

打包后代码

 

运行 npm start 打包后,我们看到打包后的文件里 class

语法已经成功转换为一个个的es5函数。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

JS删除DOM对象节点方法总结

Vue项目内应用第三方验证码

The above is the detailed content of How to convert babel to es6. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn