专栏名称: 前端JavaScript
分享 | 学习 | 交流 | 原创 分享是学习的开始;学习不必要从头开始,是从现在开始;交流能沟通你我,提高你的学识;期待你的加入!!! web前端技术交流,JavaScript,HTML5,CSS3……
目录
相关文章推荐
51好读  ›  专栏  ›  前端JavaScript

[S3-E394]JavaScript 语法树与代码转化实践

前端JavaScript  · 公众号  · Javascript  · 2017-07-29 13:32

正文

请到「今天看啥」查看全文


(foo, bar) => foo + bar;


// 简化的 AST 表示

{

"program": {

"body": [

{

"type": "ExpressionStatement",

"expression": {

"type": "ArrowFunctionExpression",

"params": [

{

"type": "Identifier",

"name": "foo"

},

{

"type": "Identifier",

"name": "bar"

}

],

"body": {

"type": "BinaryExpression",

"left": {

"type": "Identifier",

"name": "foo"

},

"operator": "+",

"right": {

"type": "Identifier",

"name": "bar"

}

}

}

}

]

}

}

我们可以使用 AST Explorer 这个工具进行在线预览与编辑;在上述的 AST 表示中,顾名思义,ArrowFunctionExpression 就表示该表达式为箭头函数表达式。该函数拥有 foo 与 bar 这两个参数,参数所属的 Identifiers 类型是没有任何子节点的变量名类型;接下来我们发现加号运算符被表示为了 BinaryExpression 类型,并且其 operator 属性设置为 +,而左右两个参数分别挂载于 left 与 right 属性下。在接下来的转化步骤中,我们即是需要对这样的抽象语法树进行转换,该步骤主要由 Babel Preset 与 Plugin 控制;Babel 内部提供了 babel-traverse 这个库来辅助进行 AST 遍历,该库还提供了一系列内置的替换与操作接口。而经过转化之后的 AST 表示如下,在实际开发中我们也常常首先对比转化前后代码的 AST 表示的不同,以了解应该进行怎样的转化操作:


// AST shortened for clarity

{

"program": {

"type": "Program",

"body": [

{

"type": "ExpressionStatement",

"expression": {

"type": "Literal",

"value": "use strict"

}

},

{

"type": "ExpressionStatement",

"expression": {

"type": "FunctionExpression",

"async": false,

"params": [

{

"type": "Identifier",

"name": "foo"

},

{

"type": "Identifier",

"name": "bar"

}

],

"body": {

"type": "BlockStatement",

"body": [

{

"type": "ReturnStatement",

"argument": {

"type": "BinaryExpression",

"left": {

"type": "Identifier",

"name": "foo"

},

"operator": "+",

"right": {

"type": "Identifier",

"name": "bar"

}

}

}

]

},

"parenthesizedExpression": true

}

}

]

}

}


自定义插件

Babel 支持以观察者(Visitor)模式定义插件,我们可以在 visitor 中预设想要观察的 Babel 结点类型,然后进行操作;譬如我们需要将下述箭头函数源代码转化为 ES5 中的函数定义:


// Source Code

const func = (foo, bar) => foo + bar;







请到「今天看啥」查看全文