转换箭头函数
一、前言
转换前:
const sum = (a,b)=>{
console.log(this);
return a+b;
}
转换后:
var _this = this;
const sum = function(a,b){
console.log(_this);
return a+b
}
二、官方实现
2.1 通过 @babel/preset-env 插件
-
安装
@babel/core
、babel-types
、@babel/preset-env
依赖- @babel/core: babel 核心包
- babel-types: babel 工具包: 1. 判断验证某个节点是不是某个类型 2.动态创建某个类型的节点
- @babel/preset-env: babel 转换库预设
-
具体实现如下:
const babelCore = require("@babel/core"); // babel 核心包
const types = require("babel-types"); // babel 工具包: 1. 判断验证某个节点是不是某个类型 2.动态创建某个类型的节点
const sourceCode = `const sum = (a,b)=>{ console.log(this); return a+b;}`;
const targetCode = babelCore.transform(sourceCode, {
presets: ["@babel/preset-env"],
});
console.log(targetCode.code);
2.2 通过 babel-plugin-transform-es2015-arrow-functions 插件
-
安装
@babel/core
、babel-types
、babel-plugin-transform-es2015-arrow-functions
依赖- @babel/core: babel 核心包
- babel-types: babel 工具包: 1. 判断验证某个节点是不是某个类型 2.动态创建某个类型的节点
- babel-plugin-transform-es2015-arrow-functions: babel 插进: 转换箭头函数
-
具体实现如下:
const babelCore = require('@babel/core'); // babel 核心包
const types = require('babel-types'); // babel 工具包: 1. 判断验证某个节点是不是某个类型 2.动态创建某个类型的节点
const transformArrowFunctions = require('babel-plugin-transform-es2015-arrow-functions'); // babel 插进: 转换箭头函数
const sourceCode = `const sum = (a,b)=>{ console.log(this); return a+b;}`;
const targetCode = babelCore.transform(sourceCode, {
plugins: [transformArrowFunctions],
});
console.log(targetCode.code);
三、模拟实现
-
安装
@babel/core
、babel-types
依赖- @babel/core: babel 核心包
- babel-types: babel 工具包: 1. 判断验证某个节点是不是某个类型 2.动态创建某个类型的节点
-
具体实现如下:
- 定义
transformArrowFunctionSelf
,用于充当转换箭头函数插件 transformArrowFunctionSelf
函数的工作如下:- 寻找箭头函数所在的上层作用域: 不是箭头函数的函数作用域或者全局作用域
- 向上层作用域添加语句:
var _this = this
- 替换箭头函数内部
this
为_this
- 改变箭头函数节点
type
为FunctionExpression
- 寻找箭头函数所在的上层作用域 通过
nodePath.findParent
来实现 - 查询箭头函数内部作用域调用 this 的地方 通过
nodePath.traverse
来实现,里面通过ThisExpression
访问器来判断是否有this
调用 - 向上层作用域添加语句 通过
thisEnvFn.scope.push
来实现 - 替换箭头函数内部
this
为_this
通过thisPath.replaceWith
来实现
const babelCore = require("@babel/core");
const types = require("babel-types");
function getScopeInfoInformation(nodePath) {
const thisPaths = [];
nodePath.traverse({
ThisExpression(thisPath) {
thisPaths.push(thisPath);
},
});
return thisPaths;
}
function hoistFunctionEnvironment(nodePath) {
const thisEnvFn = nodePath.findParent(
(p) => (p.isFunction() && !p.isArrowFunctionExpression()) || p.isProgram(),
);
const thisPaths = getScopeInfoInformation(nodePath);
const thisBinding = "_this";
if (thisPaths.length > 0) {
thisEnvFn.scope.push({
id: types.identifier(thisBinding),
init: types.thisExpression(),
});
thisPaths.forEach((thisPath) => {
const thisBindingIdentifier = types.identifier(thisBinding);
thisPath.replaceWith(thisBindingIdentifier);
});
}
}
const transformArrowFunctionSelf = {
visitor: {
ArrowFunctionExpression(nodePath) {
const { node } = nodePath;
hoistFunctionEnvironment(nodePath);
node.type = "FunctionExpression";
},
},
};
const sourceCode = `const sum = (a,b)=>{ console.log(this); return a+b;}`;
const targetCode = babelCore.transform(sourceCode, {
plugins: [transformArrowFunctionSelf],
});
console.log(targetCode.code); - 定义