-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
let esprima = require('esprima'); | ||
let estraverse = require('estraverse'); | ||
let escodegen = require('escodegen'); | ||
|
||
let code = ` | ||
function ast() {}; | ||
` | ||
|
||
// 生成语法树 | ||
let res = esprima.parse(code); | ||
|
||
// console.log(res) | ||
|
||
// 遍历语法树 (DFS) | ||
|
||
let indent = 0; | ||
const padding = () => " ".repeat(indent); | ||
estraverse.traverse(res, { | ||
enter(node) { | ||
console.log(padding() + '进入' + node.type); | ||
indent += 2; | ||
}, | ||
leave(node) { | ||
indent -= 2; | ||
console.log(padding() + '离开' + node.type); | ||
} | ||
}) | ||
|
||
// 生成语法树 | ||
let target = escodegen.generate(res); | ||
console.log(target) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const core = require('@babel/core'); | ||
const types = require('babel-types'); | ||
const plugin = require('babel-plugin-transform-es2015-arrow-functions'); | ||
|
||
const code = ` | ||
const sum = (a, b) => a + b; | ||
` | ||
// babel/core 本身只有 生成、遍历、生成 代码的功能,和上面的三个工具一样 | ||
// 它本身不会在代码遍历的时候做一个处理,除了用插件等方法 | ||
let target = core.transform(code, { | ||
plugins: [plugin] | ||
}) | ||
// console.log(target.code); | ||
|
||
// babel插件其实就是一个对象,它有一个 visitor(访问器) | ||
|
||
let myPlugin = { | ||
visitor: { | ||
/** | ||
* 函数名称就是在遍历语法树时遇到的类型,意味着给这个类型做转换 | ||
* @param {*} path 节点的数据 | ||
*/ | ||
ArrowFunctionExpression(path) { | ||
path.node.type = 'FunctionExpression'; | ||
// 只是添加这个的话 会转成 function (a, b) a + b 普通函数没有隐式返回 | ||
// 并且在箭头函数中的this没有办法取到 | ||
|
||
// 处理this指针 | ||
const thisBinding = hoistFunctionEnvironmen(path) | ||
} | ||
} | ||
} | ||
function hoistFunctionEnvironmen(fnPath) { | ||
const thisEventFn = fnPath.findParent(p => { | ||
return p.isFunction() && !p.isArrowFunctionExpression() || p.isProgram() | ||
}) | ||
} | ||
|
||
let target2 = core.transform(code, { | ||
plugins: [myPlugin] | ||
}) | ||
|
||
console.log(target2.code) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
> 相关网站 | ||
> https://www.astexplorer.net | ||
> SpiderMonkey (MDN) | ||
|
||
|
||
|
||
## 基本使用 | ||
安装依赖 | ||
|
||
`npm install esprima estraverse escodegen -S` | ||
### 解析语法树 | ||
|
||
代码: | ||
|
||
```js | ||
let esprima = require('esprima'); | ||
let estraverse = require('estraverse'); | ||
let escodegen = require('escodegen'); | ||
|
||
let code = ` | ||
function ast() {}; | ||
` | ||
|
||
let res = esprima.parse(code); | ||
|
||
console.log(res) | ||
``` | ||
|
||
运行后的结果: | ||
|
||
```js | ||
Script { | ||
type: 'Program', | ||
body: [ | ||
FunctionDeclaration { | ||
type: 'FunctionDeclaration', | ||
id: [Identifier], | ||
params: [], | ||
body: [BlockStatement], | ||
generator: false, | ||
expression: false, | ||
async: false | ||
}, | ||
EmptyStatement { type: 'EmptyStatement' } | ||
], | ||
sourceType: 'script' | ||
} | ||
``` | ||
|
||
### 遍历语法树 | ||
代码: | ||
```js | ||
// 遍历语法树 (DFS) | ||
|
||
let indent = 0; | ||
const padding = () => " ".repeat(indent); | ||
estraverse.traverse(res, { | ||
enter(node) { | ||
console.log(padding() + '进入' + node.type); | ||
indent += 2; | ||
}, | ||
leave(node) { | ||
indent -= 2; | ||
console.log(padding() + 'leave' + node.type); | ||
} | ||
}) | ||
``` | ||
|
||
结果: | ||
```txt | ||
进入Program | ||
进入FunctionDeclaration | ||
进入Identifier | ||
离开Identifier | ||
进入BlockStatement | ||
离开BlockStatement | ||
离开FunctionDeclaration | ||
进入EmptyStatement | ||
离开EmptyStatement | ||
离开Program | ||
``` | ||
|
||
### 生成语法树 | ||
|
||
代码: | ||
```js | ||
let target = escodegen.generate(res); | ||
console.log(target) | ||
``` | ||
|
||
结果: | ||
```js | ||
function ast() { | ||
} | ||
``` | ||
|
||
我们可以在第二步生成的时候,对生成的代码做一些自己的转换。 | ||
|
||
## 使用babel解析箭头函数 | ||
|
||
安装依赖 | ||
`npm install @babel/core babel-types babel-plugin-transform-es2015-arrow-functions -D` | ||
|
||
|
||
代码: | ||
```js | ||
const core = require('@babel/core'); | ||
const types = require('babel-types'); | ||
const plugin = require('babel-plugin-transform-es2015-arrow-functions'); | ||
|
||
const code = ` | ||
const sum = (a, b) => a + b; | ||
`; | ||
|
||
// babel/core 本身只有 生成、遍历、生成 代码的功能,和上面的三个工具一样 | ||
// 它本身不会在代码遍历的时候做一个处理,除了用插件等方法 | ||
let target = core.transform(code, { | ||
plugins: [plugin] // 这里如果不加plugin的话,生成的code就是源代码 | ||
}) | ||
console.log(target.code); | ||
``` | ||
|
||
结果: | ||
|
||
```js | ||
const sum = function (a, b) { | ||
return a + b; | ||
}; | ||
``` | ||
|
||
### 实现插件 | ||
|
||
```js | ||
|
||
``` |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.