babel能够转译ECMAScrIpt2015+的代码,使它能够在旧的浏览器中运行
1. babel工作分为三个部分
- 解析:将源代码转换成AST语法树
- 转换:将AST语法树进行转换
- 生成:将转换后的抽象语法树生成新的源代码
2. 简单实现babel插件
2.1 类转换成普通函数
// babel核心模块const core = require('@babel/core');// 同来生成或者判断节点的AST语法树节点let types = require('@babel/types');// 官方插件// let transformClassesPlugins = require('@babel/plugin-transform-classes');// 自己模拟插件let transformClassesPlugins = {visitor: {ClassDeclaration (path) {let node = path.node;let id = node.id;let methods = node.body.body;let nodes = [];methods.forEach(method => {// 是构造函数if (methods.kind === 'constructor') {// types.functionDeclaration 帮我们生成函数节点let constructorFunction = types.functionDeclaration(id,method.params,method.body);nodes.push(constructorFunction);} else {// 是普通函数// 表达式左边let memberExpression = types.memberExpression(types.memberExpression(id,types.identifier('prototype')),method.key);// 表达式右边let functionExpression = types.functionExpression(null,method.params,method.body);// 赋值表达式let assignmentExpression = types.assignmentExpression('=',memberExpression,functionExpression);nodes.push(assignmentExpression);}})if (nodes.length === 1) {// 单节点替换path.replaceWith(nodes[0])} else {// 多节点替换path.replaceWithMultiple(nodes)}}}};// 要转换的代码let sourceCode = `class Person {constructor (name) {this.name = name}sayName() {console.log(this.name)}}`;let tragetCode = core.transform(sourceCode, {plugins: [transformClassesPlugins]});console.log(tragetCode.code)
2.2 箭头函数转换成普通函数
// babel核心模块const core = require('@babel/core');// 同来生成或者判断节点的AST语法树节点let types = require('@babel/types');// 官方插件// let arrowFunctionPlugin = require('babel-plugin-transform-es2015-arrow-functions');// 模拟官方自定义实现let arrowFunctionPlugin = {visitor: {// 如果是箭头函数表达式,就会进入此函数,,参数是箭头函数的节点路径对象ArrowFunctionExpression(path) {let node = path.node;// 把箭头函数的type改成函数表达式的typenode.type = 'FunctionExpression';}}};// 要转换的箭头函数let sourceCode = `const sum = (a, b) => {return a + b}`;// 转换抽象语法树let tragetCode = core.transform(sourceCode, {plugins: [arrowFunctionPlugin]});console.log(tragetCode.code)
