学习 javascript AST 进阶高级程序开发

336 阅读7分钟

javascript AST node 是组成抽象语法树的最小单位的结构。可以结合AST 可视化工具进行查看。

1.ArrayExpression (数组表达式)

AST Node shape:

interface ArrayExpression {
  type: 'ArrayExpression';
  elements: Array<null | Expression | SpreadElement>;
}

例:

[1, 2, 3];

2.ArrayPattern (数组解析模式)

AST Node shape:

interface ArrayPattern {
  type: 'ArrayPattern';
  elements: Array<null | PatternLike>;
}

例:

const [a, b, c] = [1, 2, 3];

3.ArrowFunctionExpression (箭头函数表达式)

AST Node shape:

interface ArrowFunctionExpression {
  type: 'ArrowFunctionExpression';
  params: Array<Identifier | Pattern | RestElement>;
  body: BlockStatement | Expression;
  async: boolean;
  expression: boolean;
  generator: boolean;
  predicate: DeclaredPredicate | InferredPredicate;
  returnType: TypeAnnotation | TSTypeAnnotation | Noop;
  typeParameters: TypeParameterDeclaration | TSTypeParameterDeclaration | Noop;
}

例:

const getArray = () => [1, 2, 3];

4.AssignmentExpression (赋值表达式)

AST Node shape:

interface AssignmentExpression {
  type: 'AssignmentExpression';
  operator:
    | '='
    | '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | '<<='
    | '>>='
    | '>>>='
    | '|='
    | '^='
    | '&='
    | '**=';
  left: Expression;
  right: Expression;
}

例:

a += 1;

5.AssignmentPattern (赋值模式。常用于解构赋值)

AST Node shape:

interface AssignmentPattern {
  type: 'AssignmentPattern';
  left:
    | Identifier
    | ObjectPattern
    | ArrayPattern
    | MemberExpression
    | TSAsExpression
    | TSTypeAssertion
    | TSNonNullExpression;
  right: Expression;
}

例:

const [a, b, c = 3] = [1, 2, 3]; // AssignmentPattern => c = 3

6.AwaitExpression (await 表达式)

AST Node shape:

interface AwaitExpression {
  type: 'AwaitExpression';
  argument: Expression;
}

例:

await foo();

7.BinaryExpression (二元表达式)

AST Node shape:

interface BinaryExpression {
  type: 'BinaryExpression';
  operator:
    | '+'
    | '-'
    | '/'
    | '%'
    | '*'
    | '**'
    | '&'
    | '|'
    | '>>'
    | '>>>'
    | '<<'
    | '^'
    | '=='
    | '==='
    | '!='
    | '!=='
    | 'in'
    | 'instanceof'
    | '>'
    | '<'
    | '>='
    | '<='
    | '|>';
  left: Expression;
  right: Expression;
}

例:

let a = 1;
let b = 2;
if (a === b) {
  //
}

8.BlockStatement (块语句)

AST Node shape:

interface BlockStatement {
  type: 'BlockStatement';
  body: Array<Statement>;
}

例:

{
  console.log(123);
}

9.BreakStatement (break 语句)

AST Node shape:

interface BreakStatement {
  type: 'BreakStatement';
  label: Identifier;
}

例:

for (const node of [1, 2, 3]) {
  if (node >= 2) break;
  console.log(node);
}

10.CallExpression (函数执行表达式)

AST Node shape:

interface CallExpression {
  type: 'CallExpression';
  callee: Expression | V8IntrinsicIdentifier;
  arguments: Array<Expression | SpreadElement | JSXNamespacedName | ArgumentPlaceholder>;
  optional: true | false;
}

例:

const foo = () => {};
foo();

11.CatchClause (catch 语句)

AST Node shape:

interface CatchClause {
  type: 'CatchClause';
  param: Identifier | ArrayPattern | ObjectPattern;
  body: BlockStatement;
}

例:

try {
  foo();
} catch (e) {
  console.error(e);
} finally {
  bar();
}

12.ClassBody (class Body)

AST Node shape:

interface ClassBody {
  type: 'ClassBody';
  body: Array<
    | ClassMethod
    | ClassPrivateMethod
    | ClassProperty
    | ClassPrivateProperty
    | ClassAccessorProperty
    | TSDeclareMethod
    | TSIndexSignature
    | StaticBlock
  >;
}

例:

class foo {
  constructor() {}
  method() {}
}

13.ClassDeclaration (class 声明)

AST Node shape:

interface ClassDeclaration {
  type: 'ClassDeclaration';
  id: Identifier;
  superClass: Expression;
  body: ClassBody;
}

例:

class foo {
  constructor() {}
  method() {}
}

14.ClassExpression (class 表达式)

AST Node shape:

interface ClassExpression {
  type: 'ClassExpression';
  id: Identifier;
  superClass: Expression;
  body: ClassBody;
}

例:

const foo = class {
  constructor() {}
  method() {}
};

15.ConditionalExpression (条件表达式)

AST Node shape:

interface ConditionalExpression {
  type: 'ConditionalExpression';
  test: Expression;
  consequent: Expression;
  alternate: Expression;
}

例:

const a = true ? 'consequent' : 'alternate';

16.ContinueStatement (continue 语句)

AST Node shape:

interface ContinueStatement {
  type: 'ContinueStatement';
  label: Identifier;
}

例:

for (const node of [1, 2, 3]) {
  if (node === 2) continue;
  console.log(node);
}

17.DoWhileStatement (do-while 语句)

AST Node shape:

interface DoWhileStatement {
  type: 'DoWhileStatement';
  test: Expression;
  body: Statement;
}

例:

do {} while (a >= 1);

18.EmptyStatement (空语句)

AST Node shape:

interface EmptyStatement {
  type: 'EmptyStatement';
}

例:

for (const node of [1, 2, 3]);

19.ExportAllDeclaration (导出所有声明)

AST Node shape:

interface ExportAllDeclaration {
  type: 'ExportAllDeclaration';
  source: StringLiteral;
}

例:

export * from './user';

20.ExportDefaultDeclaration (导出默认声明)

AST Node shape:

interface ExportDefaultDeclaration {
  type: 'ExportDefaultDeclaration';
  declaration: FunctionDeclaration | TSDeclareFunction | ClassDeclaration | Expression;
}

例:

export default 'foo';

21.ExportNamedDeclaration (导出带名称的声明)

AST Node shape:

interface ExportNamedDeclaration {
  type: 'ExportNamedDeclaration';
  declaration: Declaration;
  specifiers: Array<ExportSpecifier | ExportDefaultSpecifier | ExportNamespaceSpecifier>;
  source: StringLiteral;
}

例:

const foo = 'foo';
export { foo };
// 或者 export const foo = 'foo';

22.ExpressionStatement (表达式语句)

AST Node shape:

interface ExpressionStatement {
  type: 'ExpressionStatement';
  expression: Expression;
}

例:

(function foo() {})();

23.ForInStatement (for...in 语句)

AST Node shape:

interface ForInStatement {
  type: 'ForInStatement';
  left: VariableDeclaration | LVal;
  right: Expression;
  body: Statement;
}

例:

for (let item in [1, 2, 3]) {
}

24.ForOfStatement (for...of 语句)

AST Node shape:

interface ForOfStatement {
  type: 'ForOfStatement';
  left: VariableDeclaration | LVal;
  right: Expression;
  body: Statement;
}

例:

for (let item of [1, 2, 3]) {
}

25.ForStatement (for 语句)

AST Node shape:

interface ForStatement {
  type: 'ForStatement';
  init: VariableDeclaration | Expression; //例如:let a = 1;
  test: Expression; //例如:a++;
  update: Expression; //例如:a < 3
  body: Statement;
}

例:

for (let a = 1; a++; a < 3) {}

26.FunctionDeclaration (for 语句)

AST Node shape:

interface FunctionDeclaration {
  type: 'FunctionDeclaration';
  id: Identifier;
  expression: boolean;
  generator: boolean;
  async: boolean;
  params: Array<Identifier | Pattern | RestElement>;
  body: BlockStatement;
}

例:

function foo() {}
//或者 function *foo(){}

27.FunctionExpression (函数表达式)

AST Node shape:

interface FunctionExpression {
  type: 'FunctionExpression';
  id: Identifier;
  expression: boolean;
  generator: boolean;
  async: boolean;
  params: Array<Identifier | Pattern | RestElement>;
  body: BlockStatement;
}

例:

const foo = function () {};

28.Identifier (标识符。就是我们写 JS 时自定义的名称,如变量名,函数名,属性名,统称为标识符。)

AST Node shape:

interface Identifier {
  type: 'Identifier';
  name: string;
}

例:

const foo = function () {};
//这个foo就是 Identifier

29.IfStatement (if 语句)

AST Node shape:

interface IfStatement {
  type: 'IfStatement';
  test: Expression;
  consequent: Statement;
  alternate: Statement;
}

例:

if (a > 1) {
}

30.ImportDeclaration (import 声明)

AST Node shape:

interface ImportDeclaration {
  type: 'ImportDeclaration';
  specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier>;
  source: StringLiteral;
}

例:

import { foo } from './user';

31.ImportDeclaration (import 声明)

AST Node shape:

interface ImportDeclaration {
  type: 'ImportDeclaration';
  specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier>;
  source: StringLiteral;
}

例:

import { foo } from './user'; //这个“foo” 就是 ImportSpecifier

32.ImportDefaultSpecifier (默认导入的标识符)

AST Node shape:

interface ImportDefaultSpecifier {
  type: 'ImportDefaultSpecifier';
  local: Identifier;
}

例:

import foo from './user'; //这个“foo” 就是 ImportDefaultSpecifier

33.ImportExpression (import 表达式)

AST Node shape:

interface ImportExpression {
  type: 'ImportExpression';
  source: StringLiteral;
}

例:

import('./user'); //source.value = './user'

34.ImportNamespaceSpecifier (带命名空间的导入标识符)

AST Node shape:

interface ImportNamespaceSpecifier {
  type: 'ImportNamespaceSpecifier';
  local: Identifier;
}

例:

import * as foo from './foo'; //ImportNamespaceSpecifier => '* as foo'

35.ImportSpecifier (导入标识符)

AST Node shape:

interface ImportSpecifier {
  type: 'ImportSpecifier';
  local: Identifier;
  imported: Identifier | StringLiteral;
}

例:

import { foo } from './foo';
//ImportSpecifier => 'foo'
// local => 'foo'

36.LabeledStatement (label 语句, 又叫标记语句。作用是在语句前面设置一个标识符。相当于将一条语句存储在一个变量里面,类似函数的函数名。)

AST Node shape:

interface LabeledStatement {
  type: 'LabeledStatement';
  label: Identifier;
  body: Statement;
}

例:

/**
 * label语句一般与 break 或者 continue 代码块一起使用
 * */

//下面这个例子在双重for循环中,实现了在内层循环结束掉外层循环的功能。
out: for (let i = 0; i < 5; i++) {
  console.log('i', i);
  for (let j = 0; j < 5; j++) {
    console.log('j', j);
    if (i == 2) {
      //todo
      break out;
    }
  }
}

//下面的例子中当i===2的时候会跳过最外层的for循环一次,因此两个for循环都只能循环4次
out: for (let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    console.log('j', j);
    if (i == 2) {
      //todo
      continue out;
    }
  }
  console.log('i', i);
}

/**
 * 与代码块一起使用
 * */
out: {
  console.log(1);
  break out;
  console.log(2);
}
console.log(3);
//依次打印 1、3

37.Literal (字面量。一般指布尔值、数值、字符串、正则表达式、null)

AST Node shape:

interface Literal {
  type: 'Literal';
  value: boolean | number | string | RegExp | null;
  raw: string;
  regex?: { pattern: string; flags: string };
}

例:

let a = 1;

38.LogicalExpression (逻辑运算符表达式)

AST Node shape:

interface LogicalExpression {
  type: 'LogicalExpression';
  operator: '||' | '&&' | '??';
  left: Expression;
  right: Expression;
}

例:

let a = true || null;

39.MemberExpression (属性成员表达式)

AST Node shape:

interface MemberExpression {
  type: 'MemberExpression';
  object: Expression;
  property: Expression;
  computed: boolean;
  optional: boolean;
}

例:

let user = { name: 'victor', age: 17 };
user.name; //MemberExpression, computed: false
user['name']; //MemberExpression, computed: true

40.MetaProperty (元数据属性。元数据,简单的来说就是描述数据的数据。例如,一个 HTML 文件是一种数据,但 HTML 文件也能在 <head> 元素中包含描述该文档的元数据,比如该文件的作者和概要。)

AST Node shape:

interface MetaProperty {
  type: 'MetaProperty';
  meta: Identifier;
  property: Identifier;
}

例:

function Vue(options) {
  if (!new.target) {
    // 这个 new.target 就是 MetaProperty, 通常"new."的作用是提供属性访问的上下文,但这里"new."其实不是一个真正的对象。
    throw new Error('Vue is a constructor and should be called with the `new` keyword');
  }
}

import.meta; //MetaProperty 通常"import."的作用是提供属性访问的上下文,但这里"import."其实不是一个真正的对象。这个对象可以扩展,并且它的属性都是可写,可配置和可枚举的。

41.MethodDefinition (类中的方法声明)

AST Node shape:

interface MethodDefinition {
  type: 'MethodDefinition';
  static: boolean;
  computed: boolean;
  key: Expression | Identifier;
  kind: 'constructor' | 'method' | 'get' | 'set';
  value: FunctionExpression;
}

例:

class Point {
  x = 0;
  y = 0;
  set point({ x, y }) {
    this.x = x;
    this.y = y;
  }

  get point() {
    return this.toString();
  }

  toString() {
    return `${this.x},${this.y}`;
  }
}

42.NewExpression (new 表达式)

AST Node shape:

interface NewExpression {
  type: 'NewExpression';
  callee: Expression;
  arguments: ExpressionNode[];
}

例:

new Promise();

43.ObjectExpression (对象表达式)

AST Node shape:

interface ObjectExpression {
  type: 'ObjectExpression';
  properties: Property[];
}

例:

let user = { name: 'victor', age: 17 };

44.ObjectPattern (对象解析模式)

AST Node shape:

interface ObjectPattern {
  type: 'ObjectPattern';
  properties: Property[];
}

例:

const { name, age } = { name: 'victor', age: 17 }; //ObjectPattern 就是 { name, age }

45.Program (源代码树)

AST Node shape:

interface Program {
  type: 'Program';
  body: StatementNode[];
  sourceType: 'module' | 'script';
}

例:

const { name, age } = { name: 'victor', age: 17 }; //指整个js文件的代码

46.Property (属性)

AST Node shape:

interface Property {
  type: 'Property';
  key: ExpressionNode;
  value: Expression | null;
  kind: 'init' | 'get' | 'set';
  method: boolean;
  shorthand: boolean;
  computed: boolean;
}

例:

const user = { name: 'victor', age: 17 };

47.PropertyDefinition (属性定义)

AST Node shape:

interface PropertyDefinition {
  type: 'PropertyDefinition';
  computed: boolean;
  static: boolean;
  key: ExpressionNode;
  value: ExpressionNode | null;
}

例:

class Point {
  x = 0; //PropertyDefinition
  y = 0; //PropertyDefinition
  set point({ x, y }) {
    this.x = x;
    this.y = y;
  }

  get point() {
    return this.toString();
  }

  toString() {
    return `${this.x},${this.y}`;
  }
}

48.RestElement (rest 参数。形式为...变量名)

AST Node shape:

interface RestElement {
  type: 'RestElement';
  argument: Identifier | PatternNode;
}

例:

function add(...values) {
  let sum = 0;
  for (var val of values) {
    sum += val;
  }
  return sum;
}

49.ReturnStatement (return 语句)

AST Node shape:

interface ReturnStatement {
  type: 'ReturnStatement';
  argument: ExpressionNode | null;
}

例:

function add(...values) {
  let sum = 0;
  for (var val of values) {
    sum += val;
  }
  return sum; //ReturnStatement
}

50.SequenceExpression (序列表达式)

AST Node shape:

interface SequenceExpression {
  type: 'SequenceExpression';
  expressions: ExpressionNode[];
}

例:

let a, b;
(a = 1), (b = 2); //SequenceExpression

51.SpreadElement (扩展运算符)

AST Node shape:

interface SpreadElement {
  type: 'SpreadElement';
  argument: Expression;
}

例:

// 扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3]);
// 1 2 3

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }

52.StaticBlock (静态块)

AST Node shape:

interface StaticBlock {
  type: 'StaticBlock';
  body: StatementNode[];
}

例:

// ES2022 引入了静态块(static block),允许在类的内部设置一个代码块,在类生成时运行且只运行一次,主要作用是对静态属性进行初始化。以后,新建类的实例时,这个块就不运行了。

class C {
  static x;
  static y;

  static {
    //todo
  }
}

53.Super (父类关键字)

AST Node shape:

interface Super {
  type: 'Super';
}

例:

class Foo {}
class Bar extends Foo {
  constructor() {
    super();
  }
}

54.SwitchCase

AST Node shape:

interface SwitchCase {
  type: 'SwitchCase';
  consequent: Statement[];
  test: Expression | null;
}

例:

let a = 1;
switch (a) {
  case (a = 1): //SwitchCase
  //todo
}

55.SwitchStatement (Switch 语句)

AST Node shape:

interface SwitchStatement {
  type: 'SwitchStatement';
  cases: SwitchCase[];
  discriminant: Expression;
}

例:

let a = 1;
switch (a) {
  case (a = 1): //SwitchCase
  //todo
}

56.TaggedTemplateExpression (带标签的模板字符串表达式)

AST Node shape:

interface TaggedTemplateExpression {
  type: 'TaggedTemplateExpression';
  quasi: TemplateLiteral;
  tag: Expression;
}

例:

// 带标签的函数的规则是普通字符串会被传到第一个参数,其他在 ${} 中的内容,则会依次传入后面的参数。
function sayHello(arg1, arg2) {
  console.log(`hello ${arg2}`);
}

sayHello`hello ${'victor'}`; //hello victor
// tag => sayHello
// quasi => `hello ${'victor'}`

57.TemplateElement (模板元素)

AST Node shape:

interface TemplateElement {
  type: 'TemplateElement';
  tail: boolean;
  value: {
    cooked: string | null;
    raw: string;
  };
}

例:

function sayHello(arg1, arg2) {
  console.log(`hello ${arg2}`); //TemplateElement => 'hello '
}

sayHello`hello ${'victor'}`; //hello victor
// tag => sayHello
// quasi => `hello ${'victor'}`

58.TemplateLiteral (模板字面量)

AST Node shape:

interface TemplateLiteral {
  type: 'TemplateLiteral';
  expressions: Expression[];
  quasis: TemplateElement[];
}

例:

let foo = `foo`;

59.ThisExpression (this 表达式)

AST Node shape:

interface ThisExpression {
  type: 'ThisExpression';
}

例:

class Foo {
  constructor() {
    this.name = 'foo';
  }
}

60.ThrowStatement (throw 语句)

AST Node shape:

interface ThrowStatement {
  type: 'ThrowStatement';
  argument: Expression;
}

例:

throw Error('uncatch error');

61.TryStatement (try 语句)

AST Node shape:

interface TryStatement {
  type: 'TryStatement';
  block: BlockStatement;
  finalizer: BlockStatement | null;
  handler: CatchClause | null;
}

例:

try {
} catch {}

62.UnaryExpression (一元操作符表达式)

AST Node shape:

interface UnaryExpression {
  type: 'UnaryExpression';
  argument: Expression;
  operator: '!' | '+' | '-' | 'delete' | 'typeof' | 'void' | '~';
  prefix: boolean;
}

例:

+1;

63.UpdateExpression (更新操作符表达式)

AST Node shape:

interface UpdateExpression {
  type: 'UpdateExpression';
  argument: Expression;
  operator: '++' | '--';
  prefix: boolean;
}

例:

++1;

64.VariableDeclaration (变量声明。包含了 kind 部分)

AST Node shape:

interface VariableDeclaration {
  type: 'VariableDeclaration';
  declarations: VariableDeclarator[];
  kind: 'var' | 'let' | 'const';
}

例:

let foo = 'foo';

65.VariableDeclarator (变量声明。不含 kind 部分)

AST Node shape:

interface VariableDeclaration {
  type: 'VariableDeclaration';
  id: PatternNode;
  init: Expression | null;
}

例:

let foo = 'foo';

66.WhileStatement (while 语句)

AST Node shape:

interface WhileStatement {
  type: 'WhileStatement';
  body: Statement;
  test: Expression;
}

例:

while (true) {}

67.YieldExpression (yield 表达式)

AST Node shape:

interface YieldExpression {
  type: 'YieldExpression';
  argument: Expression | null;
  delegate: boolean;
}

例:

function* foo() {
  yield 'a';
  yield 'b';
}