We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Babel为当前最流行的代码JavaScript编译器了,其使用的JavaScript解析器为babel-parser,最初是从Acorn 项目fork出来的。Acorn 非常快,易于使用,并且针对非标准特性(以及那些未来的标准特性) 设计了一个基于插件的架构。本文主要介绍esprima解析生成的抽象语法树节点,esprima的实现也是基于Acorn的。
Acorn
fork
esprima
JavaScript Parser 是把js源码转化为抽象语法树(AST)的解析器。这个步骤分为两个阶段:词法分析(Lexical Analysis) 和 语法分析(Syntactic Analysis)。
常用的JavaScript Parser:
uglifyJS2
traceur
acorn
espree
@babel/parser
词法分析阶段把字符串形式的代码转换为 令牌(tokens)流。你可以把令牌看作是一个扁平的语法片段数组。
n * n;
例如上面n*n的词法分析得到结果如下:
n*n
[ { type: { ... }, value: "n", start: 0, end: 1, loc: { ... } }, { type: { ... }, value: "*", start: 2, end: 3, loc: { ... } }, { type: { ... }, value: "n", start: 4, end: 5, loc: { ... } }, ]
每一个 type 有一组属性来描述该令牌:
{ type: { label: 'name', keyword: undefined, beforeExpr: false, startsExpr: true, rightAssociative: false, isLoop: false, isAssign: false, prefix: false, postfix: false, binop: null, updateContext: null }, ... }
和 AST 节点一样它们也有 start,end,loc 属性。
语法分析就是根据词法分析的结果,也就是令牌tokens,将其转换成AST。
function square(n) { return n * n; }
如上面代码,生成的AST结构如下:
{ type: "FunctionDeclaration", id: { type: "Identifier", name: "square" }, params: [{ type: "Identifier", name: "n" }], body: { type: "BlockStatement", body: [{ type: "ReturnStatement", argument: { type: "BinaryExpression", operator: "*", left: { type: "Identifier", name: "n" }, right: { type: "Identifier", name: "n" } } }] } }
下文将对AST各个类型节点做解释。更多AST生成,入口如下:
eslint
AST Explorer
结合可视化工具,举个例子
如下代码:
var a = 42; var b = 5; function addA(d) { return a + d; } var c = addA(2) + b;
第一步词法分析之后长成如下图所示:
语法分析,生产抽象语法树,生成的抽象语法树如下图所示
所有节点类型都实现以下接口:
interface Node { type: string; range?: [number, number]; loc?: SourceLocation; }
该type字段是表示AST变体类型的字符串。该loc字段表示节点的源位置信息。如果解析器没有生成有关节点源位置的信息,则该字段为null;否则它是一个对象,包括一个起始位置(被解析的源区域的第一个字符的位置)和一个结束位置.
interface SourceLocation { start: Position; end: Position; source?: string | null; }
每个Position对象由一个line数字(1索引)和一个column数字(0索引)组成:
interface Position { line: uint32 >= 1; column: uint32 >= 0; }
interface Program <: Node { type: "Program"; sourceType: 'script' | 'module'; body: StatementListItem[] | ModuleItem[]; }
表示一个完整的源代码树。
源代码数的来源包括两种,一种是script脚本,一种是modules模块
当为script时,body为StatementListItem。 当为modules时,body为ModuleItem。
StatementListItem
ModuleItem
类型StatementListItem和ModuleItem类型如下。
type StatementListItem = Declaration | Statement; type ModuleItem = ImportDeclaration | ExportDeclaration | StatementListItem;
import语法,导入模块
type ImportDeclaration { type: 'ImportDeclaration'; specifiers: ImportSpecifier[]; source: Literal; }
ImportSpecifier类型如下:
ImportSpecifier
interface ImportSpecifier { type: 'ImportSpecifier' | 'ImportDefaultSpecifier' | 'ImportNamespaceSpecifier'; local: Identifier; imported?: Identifier; }
ImportSpecifier语法如下:
import { foo } from './foo';
ImportDefaultSpecifier语法如下:
ImportDefaultSpecifier
import foo from './foo';
ImportNamespaceSpecifier语法如下
ImportNamespaceSpecifier
import * as foo from './foo';
export类型如下
type ExportDeclaration = ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration;
ExportAllDeclaration从指定模块中导出
ExportAllDeclaration
interface ExportAllDeclaration { type: 'ExportAllDeclaration'; source: Literal; }
语法如下:
export * from './foo';
ExportDefaultDeclaration导出默认模块
ExportDefaultDeclaration
interface ExportDefaultDeclaration { type: 'ExportDefaultDeclaration'; declaration: Identifier | BindingPattern | ClassDeclaration | Expression | FunctionDeclaration; }
语法如下:
export default 'foo';
ExportNamedDeclaration导出部分模块
ExportNamedDeclaration
interface ExportNamedDeclaration { type: 'ExportNamedDeclaration'; declaration: ClassDeclaration | FunctionDeclaration | VariableDeclaration; specifiers: ExportSpecifier[]; source: Literal; }
export const foo = 'foo';
declaration,即声明,类型如下:
declaration
type Declaration = VariableDeclaration | FunctionDeclaration | ClassDeclaration;
statements,即语句,类型如下:
statements
type Statement = BlockStatement | BreakStatement | ContinueStatement | DebuggerStatement | DoWhileStatement | EmptyStatement | ExpressionStatement | ForStatement | ForInStatement | ForOfStatement | FunctionDeclaration | IfStatement | LabeledStatement | ReturnStatement | SwitchStatement | ThrowStatement | TryStatement | VariableDeclaration | WhileStatement | WithStatement;
变量声明,kind 属性表示是什么类型的声明,因为 ES6 引入了 const/let。
interface VariableDeclaration <: Declaration { type: "VariableDeclaration"; declarations: [ VariableDeclarator ]; kind: "var" | "let" | "const"; }
函数声明(非函数表达式)
interface FunctionDeclaration { type: 'FunctionDeclaration'; id: Identifier | null; params: FunctionParameter[]; body: BlockStatement; generator: boolean; async: boolean; expression: false; }
例如:
function foo() {} function *bar() { yield "44"; } async function noop() { await new Promise(function(resolve, reject) { resolve('55'); }) }
类声明(非类表达式)
interface ClassDeclaration { type: 'ClassDeclaration'; id: Identifier | null; superClass: Identifier | null; body: ClassBody; }
ClassBody声明如下:
ClassBody
interface ClassBody { type: 'ClassBody'; body: MethodDefinition[]; }
MethodDefinition表示方法声明;
MethodDefinition
interface MethodDefinition { type: 'MethodDefinition'; key: Expression | null; computed: boolean; value: FunctionExpression | null; kind: 'method' | 'constructor'; static: boolean; }
class foo { constructor() {} method() {} };
continue语句
interface ContinueStatement { type: 'ContinueStatement'; label: Identifier | null; }
for (var i = 0; i < 10; i++) { if (i === 0) { continue; } }
debugger语句
interface DebuggerStatement { type: 'DebuggerStatement'; }
例如
while(true) { debugger; }
do-while语句
interface DoWhileStatement { type: 'DoWhileStatement'; body: Statement; test: Expression; }
test表示while条件
test
var i = 0; do { i++; } while(i = 2)
空语句
interface EmptyStatement { type: 'EmptyStatement'; }
if(true); var a = []; for(i = 0; i < a.length; a[i++] = 0);
表达式语句,即,由单个表达式组成的语句。
interface ExpressionStatement { type: 'ExpressionStatement'; expression: Expression; directive?: string; }
当表达式语句表示一个指令(例如“use strict”)时,directive属性将包含该指令字符串。
(function(){});
for语句
interface ForStatement { type: 'ForStatement'; init: Expression | VariableDeclaration | null; test: Expression | null; update: Expression | null; body: Statement; }
for...in语句
interface ForInStatement { type: 'ForInStatement'; left: Expression; right: Expression; body: Statement; each: false; }
for...of语句
interface ForOfStatement { type: 'ForOfStatement'; left: Expression; right: Expression; body: Statement; }
if 语句
interface IfStatement { type: 'IfStatement'; test: Expression; consequent: Statement; alternate?: Statement; }
consequent表示if命中后内容,alternate表示else或者else if的内容。
consequent
alternate
label语句,多用于精确的使用嵌套循环中的continue和break。
interface LabeledStatement { type: 'LabeledStatement'; label: Identifier; body: Statement; }
如:
var num = 0; outPoint: for (var i = 0 ; i < 10 ; i++){ for (var j = 0 ; j < 10 ; j++){ if( i == 5 && j == 5 ){ break outPoint; } num++; } }
return 语句
interface ReturnStatement { type: 'ReturnStatement'; argument: Expression | null; }
Switch语句
interface SwitchStatement { type: 'SwitchStatement'; discriminant: Expression; cases: SwitchCase[]; }
discriminant表示switch的变量。
discriminant
SwitchCase类型如下
SwitchCase
interface SwitchCase { type: 'SwitchCase'; test: Expression | null; consequent: Statement[]; }
throw语句
interface ThrowStatement { type: 'ThrowStatement'; argument: Expression; }
try...catch语句
interface TryStatement { type: 'TryStatement'; block: BlockStatement; handler: CatchClause | null; finalizer: BlockStatement | null; }
handler为catch处理声明内容,finalizer为finally内容。
handler
finalizer
CatchClaus 类型如下
CatchClaus
interface CatchClause { type: 'CatchClause'; param: Identifier | BindingPattern; body: BlockStatement; }
try { foo(); } catch (e) { console.erroe(e); } finally { bar(); }
while语句
interface WhileStatement { type: 'WhileStatement'; test: Expression; body: Statement; }
test为判定表达式
with语句(指定块语句的作用域)
interface WithStatement { type: 'WithStatement'; object: Expression; body: Statement; }
var a = {}; with(a) { name = 'xiao.ming'; } console.log(a); // {name: 'xiao.ming'}
Expressions可用类型如下:
Expressions
type Expression = ThisExpression | Identifier | Literal | ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | ClassExpression | TaggedTemplateExpression | MemberExpression | Super | MetaProperty | NewExpression | CallExpression | UpdateExpression | AwaitExpression | UnaryExpression | BinaryExpression | LogicalExpression | ConditionalExpression | YieldExpression | AssignmentExpression | SequenceExpression;
Patterns可用有两种类型,函数模式和对象模式如下:
Patterns
type BindingPattern = ArrayPattern | ObjectPattern;
this 表达式
this
interface ThisExpression { type: 'ThisExpression'; }
标识符,就是我们写 JS 时自定义的名称,如变量名,函数名,属性名,都归为标识符。相应的接口是这样的:
interface Identifier { type: 'Identifier'; name: string; }
字面量,这里不是指 [] 或者 {} 这些,而是本身语义就代表了一个值的字面量,如 1,“hello”, true 这些,还有正则表达式(有一个扩展的 Node 来表示正则表达式),如 /\d?/。
interface Literal { type: 'Literal'; value: boolean | number | string | RegExp | null; raw: string; regex?: { pattern: string, flags: string }; }
var a = 1; var b = 'b'; var c = false; var d = /\d/;
数组表达式
interface ArrayExpression { type: 'ArrayExpression'; elements: ArrayExpressionElement[]; }
例:
[1, 2, 3, 4];
数组表达式的节点,类型如下
type ArrayExpressionElement = Expression | SpreadElement;
Expression包含所有表达式,SpreadElement为扩展运算符语法。
扩展运算符
interface SpreadElement { type: 'SpreadElement'; argument: Expression; }
var a = [3, 4]; var b = [1, 2, ...a]; var c = {foo: 1}; var b = {bar: 2, ...c};
对象表达式
interface ObjectExpression { type: 'ObjectExpression'; properties: Property[]; }
Property代表为对象的属性描述
Property
类型如下
interface Property { type: 'Property'; key: Expression; computed: boolean; value: Expression | null; kind: 'get' | 'set' | 'init'; method: false; shorthand: boolean; }
kind用来表示是普通的初始化,或者是 get/set。
kind
var obj = { foo: 'foo', bar: function() {}, noop() {}, // method 为 true ['computed']: 'computed' // computed 为 true }
函数表达式
interface FunctionExpression { type: 'FunctionExpression'; id: Identifier | null; params: FunctionParameter[]; body: BlockStatement; generator: boolean; async: boolean; expression: boolean; }
var foo = function () {}
箭头函数表达式
interface ArrowFunctionExpression { type: 'ArrowFunctionExpression'; id: Identifier | null; params: FunctionParameter[]; body: BlockStatement | Expression; generator: boolean; async: boolean; expression: false; }
generator表示是否为generator函数,async表示是否为async/await函数,params为参数定义。
generator
async
params
FunctionParameter类型如下
FunctionParameter
type FunctionParameter = AssignmentPattern | Identifier | BindingPattern;
例:
var foo = () => {};
类表达式
interface ClassExpression { type: 'ClassExpression'; id: Identifier | null; superClass: Identifier | null; body: ClassBody; }
var foo = class { constructor() {} method() {} };
标记模板文字函数
interface TaggedTemplateExpression { type: 'TaggedTemplateExpression'; readonly tag: Expression; readonly quasi: TemplateLiteral; }
TemplateLiteral类型如下
TemplateLiteral
interface TemplateLiteral { type: 'TemplateLiteral'; quasis: TemplateElement[]; expressions: Expression[]; }
TemplateElement类型如下
TemplateElement
interface TemplateElement { type: 'TemplateElement'; value: { cooked: string; raw: string }; tail: boolean; }
var foo = function(a){ console.log(a); } foo`test`;
属性成员表达式
interface MemberExpression { type: 'MemberExpression'; computed: boolean; object: Expression; property: Expression; }
const foo = {bar: 'bar'}; foo.bar; foo['bar']; // computed 为 true
父类关键字
interface Super { type: 'Super'; }
例如:
class foo {}; class bar extends foo { constructor() { super(); } }
(这个不知道干嘛用的)
interface MetaProperty { type: 'MetaProperty'; meta: Identifier; property: Identifier; }
new.target // 通过new 声明的对象,new.target会存在 import.meta
函数执行表达式
interface CallExpression { type: 'CallExpression'; callee: Expression | Import; arguments: ArgumentListElement[]; }
Import类型,没搞懂。
interface Import { type: 'Import' }
ArgumentListElement类型
ArgumentListElement
type ArgumentListElement = Expression | SpreadElement;
var foo = function (){}; foo();
new 表达式
interface NewExpression { type: 'NewExpression'; callee: Expression; arguments: ArgumentListElement[]; }
更新操作符表达式,如++、--;
++
--
interface UpdateExpression { type: "UpdateExpression"; operator: '++' | '--'; argument: Expression; prefix: boolean; }
如:
var i = 0; i++; ++i; // prefix为true
await表达式,会与async连用。
interface AwaitExpression { type: 'AwaitExpression'; argument: Expression; }
如
async function foo() { var bar = function() { new Primise(function(resolve, reject) { setTimeout(function() { resove('foo') }, 1000); }); } return await bar(); } foo() // foo
一元操作符表达式
interface UnaryExpression { type: "UnaryExpression"; operator: UnaryOperator; prefix: boolean; argument: Expression; }
枚举UnaryOperator
UnaryOperator
enum UnaryOperator { "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" | "throw" }
二元操作符表达式
interface BinaryExpression { type: 'BinaryExpression'; operator: BinaryOperator; left: Expression; right: Expression; }
枚举BinaryOperator
BinaryOperator
enum BinaryOperator { "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | "instanceof" | "|>" }
逻辑运算符表达式
interface LogicalExpression { type: 'LogicalExpression'; operator: '||' | '&&'; left: Expression; right: Expression; }
var a = '-'; var b = a || '-'; if (a && b) {}
条件运算符
interface ConditionalExpression { type: 'ConditionalExpression'; test: Expression; consequent: Expression; alternate: Expression; }
var a = true; var b = a ? 'consequent' : 'alternate';
yield表达式
interface YieldExpression { type: 'YieldExpression'; argument: Expression | null; delegate: boolean; }
function* gen(x) { var y = yield x + 2; return y; }
赋值表达式。
interface AssignmentExpression { type: 'AssignmentExpression'; operator: '=' | '*=' | '**=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|='; left: Expression; right: Expression; }
operator属性表示一个赋值运算符,left和right是赋值运算符左右的表达式。
operator
left
right
序列表达式(使用逗号)。
interface SequenceExpression { type: 'SequenceExpression'; expressions: Expression[]; }
var a, b; a = 1, b = 2
数组解析模式
interface ArrayPattern { type: 'ArrayPattern'; elements: ArrayPatternElement[]; }
const [a, b] = [1,3];
elements代表数组节点
ArrayPatternElement如下
type ArrayPatternElement = AssignmentPattern | Identifier | BindingPattern | RestElement | null;
默认赋值模式,数组解析、对象解析、函数参数默认值使用。
interface AssignmentPattern { type: 'AssignmentPattern'; left: Identifier | BindingPattern; right: Expression; }
const [a, b = 4] = [1,3];
剩余参数模式,语法与扩展运算符相近。
interface RestElement { type: 'RestElement'; argument: Identifier | BindingPattern; }
const [a, b, ...c] = [1, 2, 3, 4];
对象解析模式
interface ObjectPattern { type: 'ObjectPattern'; properties: Property[]; }
const object = {a: 1, b: 2}; const { a, b } = object;
AST的作用大致分为几类
IDE使用,如代码风格检测(eslint等)、代码的格式化,代码高亮,代码错误等等
代码的混淆压缩
转换代码的工具。如webpack,rollup,各种代码规范之间的转换,ts,jsx等转换为原生js
了解AST,最终还是为了让我们了解我们使用的工具,当然也让我们更了解JavaScript,更靠近JavaScript。
前端进阶之 Javascript 抽象语法树
抽象语法树(Abstract Syntax Tree)
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
Babel为当前最流行的代码JavaScript编译器了,其使用的JavaScript解析器为babel-parser,最初是从
Acorn
项目fork
出来的。Acorn 非常快,易于使用,并且针对非标准特性(以及那些未来的标准特性) 设计了一个基于插件的架构。本文主要介绍esprima
解析生成的抽象语法树节点,esprima
的实现也是基于Acorn的。解析器 Parser
JavaScript Parser 是把js源码转化为抽象语法树(AST)的解析器。这个步骤分为两个阶段:词法分析(Lexical Analysis) 和 语法分析(Syntactic Analysis)。
常用的JavaScript Parser:
esprima
uglifyJS2
traceur
acorn
espree
@babel/parser
词法分析
词法分析阶段把字符串形式的代码转换为 令牌(tokens)流。你可以把令牌看作是一个扁平的语法片段数组。
例如上面
n*n
的词法分析得到结果如下:每一个 type 有一组属性来描述该令牌:
和 AST 节点一样它们也有 start,end,loc 属性。
语法分析
语法分析就是根据词法分析的结果,也就是令牌tokens,将其转换成AST。
如上面代码,生成的AST结构如下:
下文将对AST各个类型节点做解释。更多AST生成,入口如下:
eslint
AST Explorer
esprima
结合可视化工具,举个例子
如下代码:
第一步词法分析之后长成如下图所示:
语法分析,生产抽象语法树,生成的抽象语法树如下图所示
Base
Node
所有节点类型都实现以下接口:
该type字段是表示AST变体类型的字符串。该loc字段表示节点的源位置信息。如果解析器没有生成有关节点源位置的信息,则该字段为null;否则它是一个对象,包括一个起始位置(被解析的源区域的第一个字符的位置)和一个结束位置.
每个Position对象由一个line数字(1索引)和一个column数字(0索引)组成:
Programs
表示一个完整的源代码树。
Scripts and Modules
源代码数的来源包括两种,一种是script脚本,一种是modules模块
当为script时,body为
StatementListItem
。当为modules时,body为
ModuleItem
。类型
StatementListItem
和ModuleItem
类型如下。ImportDeclaration
import语法,导入模块
ImportSpecifier
类型如下:ImportSpecifier
语法如下:ImportDefaultSpecifier
语法如下:ImportNamespaceSpecifier
语法如下ExportDeclaration
export类型如下
ExportAllDeclaration
从指定模块中导出语法如下:
ExportDefaultDeclaration
导出默认模块语法如下:
ExportNamedDeclaration
导出部分模块语法如下:
Declarations and Statements
declaration
,即声明,类型如下:statements
,即语句,类型如下:VariableDeclarator
变量声明,kind 属性表示是什么类型的声明,因为 ES6 引入了 const/let。
FunctionDeclaration
函数声明(非函数表达式)
例如:
ClassDeclaration
类声明(非类表达式)
ClassBody
声明如下:MethodDefinition
表示方法声明;ContinueStatement
continue语句
例如:
DebuggerStatement
debugger语句
例如
DoWhileStatement
do-while语句
test
表示while条件例如:
EmptyStatement
空语句
例如:
ExpressionStatement
表达式语句,即,由单个表达式组成的语句。
当表达式语句表示一个指令(例如“use strict”)时,directive属性将包含该指令字符串。
例如:
ForStatement
for语句
ForInStatement
for...in语句
ForOfStatement
for...of语句
IfStatement
if 语句
consequent
表示if命中后内容,alternate
表示else或者else if的内容。LabeledStatement
label语句,多用于精确的使用嵌套循环中的continue和break。
如:
ReturnStatement
return 语句
SwitchStatement
Switch语句
discriminant
表示switch的变量。SwitchCase
类型如下ThrowStatement
throw语句
TryStatement
try...catch语句
handler
为catch处理声明内容,finalizer
为finally内容。CatchClaus
类型如下例如:
WhileStatement
while语句
test
为判定表达式WithStatement
with语句(指定块语句的作用域)
如:
Expressions and Patterns
Expressions
可用类型如下:Patterns
可用有两种类型,函数模式和对象模式如下:ThisExpression
this
表达式Identifier
标识符,就是我们写 JS 时自定义的名称,如变量名,函数名,属性名,都归为标识符。相应的接口是这样的:
Literal
字面量,这里不是指 [] 或者 {} 这些,而是本身语义就代表了一个值的字面量,如 1,“hello”, true 这些,还有正则表达式(有一个扩展的 Node 来表示正则表达式),如 /\d?/。
例如:
ArrayExpression
数组表达式
例:
ArrayExpressionElement
数组表达式的节点,类型如下
Expression包含所有表达式,SpreadElement为扩展运算符语法。
SpreadElement
扩展运算符
如:
ObjectExpression
对象表达式
Property
代表为对象的属性描述类型如下
kind
用来表示是普通的初始化,或者是 get/set。例如:
FunctionExpression
函数表达式
例如:
ArrowFunctionExpression
箭头函数表达式
generator
表示是否为generator函数,async
表示是否为async/await函数,params
为参数定义。FunctionParameter
类型如下例:
ClassExpression
类表达式
例如:
TaggedTemplateExpression
标记模板文字函数
TemplateLiteral
类型如下TemplateElement
类型如下例如
MemberExpression
属性成员表达式
例如:
Super
父类关键字
例如:
MetaProperty
(这个不知道干嘛用的)
例如:
CallExpression
函数执行表达式
Import类型,没搞懂。
ArgumentListElement
类型如:
NewExpression
new 表达式
UpdateExpression
更新操作符表达式,如
++
、--
;如:
AwaitExpression
await表达式,会与async连用。
如
UnaryExpression
一元操作符表达式
枚举
UnaryOperator
BinaryExpression
二元操作符表达式
枚举
BinaryOperator
LogicalExpression
逻辑运算符表达式
如:
ConditionalExpression
条件运算符
例如:
YieldExpression
yield表达式
例如:
AssignmentExpression
赋值表达式。
operator
属性表示一个赋值运算符,left
和right
是赋值运算符左右的表达式。SequenceExpression
序列表达式(使用逗号)。
ArrayPattern
数组解析模式
例:
elements代表数组节点
ArrayPatternElement如下
AssignmentPattern
默认赋值模式,数组解析、对象解析、函数参数默认值使用。
例:
RestElement
剩余参数模式,语法与扩展运算符相近。
例:
ObjectPatterns
对象解析模式
例:
结束
AST的作用大致分为几类
IDE使用,如代码风格检测(eslint等)、代码的格式化,代码高亮,代码错误等等
代码的混淆压缩
转换代码的工具。如webpack,rollup,各种代码规范之间的转换,ts,jsx等转换为原生js
了解AST,最终还是为了让我们了解我们使用的工具,当然也让我们更了解JavaScript,更靠近JavaScript。
参考文献
前端进阶之 Javascript 抽象语法树
抽象语法树(Abstract Syntax Tree)
The text was updated successfully, but these errors were encountered: