iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >前端要知道的AST知识有哪些
  • 159
分享到

前端要知道的AST知识有哪些

2023-07-06 03:07:48 159人浏览 安东尼
摘要

本篇内容主要讲解“前端要知道的AST知识有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“前端要知道的AST知识有哪些”吧!认识 AST定义:在计算机科学中,抽象语法树是源代码语法结构的一种抽

本篇内容主要讲解“前端要知道的AST知识有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“前端要知道的AST知识有哪些”吧!

认识 AST

定义:在计算机科学中,抽象语法树是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每个细节。

从定义中我们只需要知道一件事就行,那就是 AST 是一种树形结构,并且是某种代码的一种抽象表示。

estree[1]

estree 就是 es 语法对应的标准 AST,作为一个前端也比较方便理解。我们以官方文档为例

https://GitHub.com/estree/estree/blob/master/es5.md

下面看一个代码

console.log('1')

AST 为

{  "type": "Program",  "start": 0, // 起始位置  "end": 16, // 结束位置,字符长度  "body": [    {      "type": "ExpressionStatement", // 表达式语句      "start": 0,      "end": 16,      "expression": {        "type": "CallExpression", // 函数方法调用式        "start": 0,        "end": 16,        "callee": {          "type": "MemberExpression", // 成员表达式 console.log          "start": 0,          "end": 11,          "object": {            "type": "Identifier", // 标识符,可以是表达式或者结构模式            "start": 0,            "end": 7,            "name": "console"          },          "property": {            "type": "Identifier",             "start": 8,            "end": 11,            "name": "log"          },          "computed": false, // 成员表达式的计算结果,如果为 true 则是 console[log], false 则为 console.log          "optional": false        },        "arguments": [ // 参数          {            "type": "Literal", // 文字标记,可以是表达式            "start": 12,            "end": 15,            "value": "1",            "raw": "'1'"          }        ],        "optional": false      }    }  ],  "sourceType": "module"}

看两个稍微复杂的代码

const b = { a: 1 };const { a } = b;
function add(a, b) {    return a + b;}

认识 acorn[2]

javascript 编写的 JavaScript 解析器,类似的解析器还有很多,比如 Esprima[3] 和 Shift[4] ,关于他们的性能,Esprima 的官网给了个测试地址[5],但是由于 acron 代码比较精简,且 webpack 和 eslint 都依赖 acorn,因此我们这次从 acorn 下手,了解如何使用 AST。

基本操作

acorn 的操作很简单

import * as acorn from 'acorn';const code = 'xxx';const ast = acorn.parse(code, options)

这样我们就能拿到代码的 ast 了,options 的定义如下

  interface Options {    ecmaVersion: 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 'latest'    sourceType?: 'script' | 'module'    onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void    onTrailinGComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void    allowReserved?: boolean | 'never'    allowReturnOutsideFunction?: boolean    allowImportExportEverywhere?: boolean    allowAwaitOutsideFunction?: boolean    allowSuperOutsideMethod?: boolean    allowHashBang?: boolean    locations?: boolean    onToken?: ((token: Token) => any) | Token[]    onComment?: ((      isBlock: boolean, text: string, start: number, end: number, startLoc?: Position,      endLoc?: Position    ) => void) | Comment[]    ranges?: boolean    program?: node    sourceFile?: string    directSourceFile?: string    preserveParens?: boolean  }
  • ecmaVersion ECMA 版本,默认时 es7

  • locations 默认为 false,设置为 true 时节点会携带一个 loc 对象来表示当前开始与结束的行数。

  • onComment 回调函数,每当代码执行到注释的时候都会触发,可以获取当前的注释内容

获得 ast 之后我们想还原之前的函数怎么办,这里可以使用 astring[6]

import * as astring from 'astring'; const code = astring.generate(ast);
实现普通函数转换为箭头函数

接下来我们就可以利用 AST 来实现一些字符串匹配不太容易实现的操作,比如将普通函数转化为箭头函数。

我们先来看两个函数的AST有什么区别

function add(a, b) {    return a + b;}
const add = (a, b) => {    return a + b;}
{  "type": "Program",  "start": 0,  "end": 41,  "body": [    {      "type": "FunctionDeclaration",      "start": 0,      "end": 40,      "id": {        "type": "Identifier",        "start": 9,        "end": 12,        "name": "add"      },      "expression": false,      "generator": false,      "async": false,      "params": [        {          "type": "Identifier",          "start": 13,          "end": 14,          "name": "a"        },        {          "type": "Identifier",          "start": 16,          "end": 17,          "name": "b"        }      ],      "body": {        "type": "BlockStatement",        "start": 19,        "end": 40,        "body": [          {            "type": "ReturnStatement",            "start": 25,            "end": 38,            "argument": {              "type": "BinaryExpression",              "start": 32,              "end": 37,              "left": {                "type": "Identifier",                "start": 32,                "end": 33,                "name": "a"              },              "operator": "+",              "right": {                "type": "Identifier",                "start": 36,                "end": 37,                "name": "b"              }            }          }        ]      }    }  ],  "sourceType": "module"}
{  "type": "Program",  "start": 0,  "end": 43,  "body": [    {      "type": "VariableDeclaration",      "start": 0,      "end": 43,      "declarations": [        {          "type": "VariableDeclarator",          "start": 6,          "end": 43,          "id": {            "type": "Identifier",            "start": 6,            "end": 9,            "name": "add"          },          "init": {            "type": "ArrowFunctionExpression",            "start": 12,            "end": 43,            "id": null,            "expression": false,            "generator": false,            "async": false,            "params": [              {                "type": "Identifier",                "start": 13,                "end": 14,                "name": "a"              },              {                "type": "Identifier",                "start": 16,                "end": 17,                "name": "b"              }            ],            "body": {              "type": "BlockStatement",              "start": 22,              "end": 43,              "body": [                {                  "type": "ReturnStatement",                  "start": 28,                  "end": 41,                  "argument": {                    "type": "BinaryExpression",                    "start": 35,                    "end": 40,                    "left": {                      "type": "Identifier",                      "start": 35,                      "end": 36,                      "name": "a"                    },                    "operator": "+",                    "right": {                      "type": "Identifier",                      "start": 39,                      "end": 40,                      "name": "b"                    }                  }                }              ]            }          }        }      ],      "kind": "const"    }  ],  "sourceType": "module"}

找到区别之后我们就可以有大致的思路

  1. 找到 FunctionDeclaration

  2. 将其替换为VariableDeclaration VariableDeclarator 节点

  3. 在 VariableDeclarator 节点的 init 属性下新建 ArrowFunctionExpression 节点

  4. 并将 FunctionDeclaration 节点的相关属性替换到 ArrowFunctionExpression 上即可

但是由于 acorn 处理的 ast 只是单纯的对象,并不具备类似 dom 节点之类的对节点的操作能力,如果需要操作节点,需要写很多工具函数, 所以我这里就简单写一下。

import * as acorn from "acorn";import * as astring from 'astring';import { createNode, walkNode } from "./utils.js"; const code = 'function add(a, b) { return a+b; } function dd(a) { return a + 1 }';console.log('in:', code);const ast = acorn.parse(code); walkNode(ast, (node) => {    if(node.type === 'FunctionDeclaration') {        node.type = 'VariableDeclaration';        const variableDeclaratorNode = createNode('VariableDeclarator');        variableDeclaratorNode.id = node.id;        delete node.id;        const arrowFunctionExpressionNode = createNode('ArrowFunctionExpression');        arrowFunctionExpressionNode.params = node.params;        delete node.params;        arrowFunctionExpressionNode.body = node.body;        delete node.body;        variableDeclaratorNode.init = arrowFunctionExpressionNode;        node.declarations = [variableDeclaratorNode];        node.kind = 'const';    }}) console.log('out:', astring.generate(ast))

结果如下

前端要知道的AST知识有哪些

如果想要代码更加健壮,可以使用 recast[7],提供了对 ast 的各种操作

// 用螺丝刀解析机器const ast = recast.parse(code); // ast可以处理很巨大的代码文件// 但我们现在只需要代码块的第一个body,即add函数const add  = ast.program.body[0] console.log(add) // 引入变量声明,变量符号,函数声明三种“模具”const {variableDeclaration, variableDeclarator, functionExpression} = recast.types.builders // 将准备好的组件置入模具,并组装回原来的ast对象。ast.program.body[0] = variableDeclaration("const", [  variableDeclarator(add.id, functionExpression(    null, // Anonymize the function expression.    add.params,    add.body  ))]); //将AST对象重新转回可以阅读的代码const output = recast.print(ast).code; console.log(output)

这里只是示例代码,展示 recast 的一些操作,最好的情况还是能遍历节点自动替换。

这样我们就完成了将普通函数转换成箭头函数的操作,但 ast 的作用不止于此,作为一个前端在工作中可能涉及 ast 的地方,就是自定义 eslint 、 stylelint 等插件

到此,相信大家对“前端要知道的AST知识有哪些”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 前端要知道的AST知识有哪些

本文链接: https://www.lsjlt.com/news/357443.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 前端要知道的AST知识有哪些
    本篇内容主要讲解“前端要知道的AST知识有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“前端要知道的AST知识有哪些”吧!认识 AST定义:在计算机科学中,抽象语法树是源代码语法结构的一种抽...
    99+
    2023-07-06
  • 关于前端要知道的 AST知识
    目录认识 ASTestree[1]认识 acorn[2]基本操作实现普通函数转换为箭头函数认识 AST 定义:在计算机科学中,抽象语法树是源代码语法结构的一种抽象表示。它以...
    99+
    2023-05-15
    前端 前端AST知识
  • C#中所要知道的知识点有哪些
    本文小编为大家详细介绍“C#中所要知道的知识点有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#中所要知道的知识点有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.在C#中,类名首字母需大写。如:c...
    99+
    2023-07-05
  • css前端知识点有哪些
    本篇文章给大家分享的是有关css前端知识点有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、css的概念:(CascadingStyleSheet级联样式表)优点:1.内...
    99+
    2023-06-08
  • ASP新手要知道的基础知识有哪些
    ASP新手要知道的基础知识有哪些,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。我们都知道,ASP是Active Server Page的缩写,意为“动态服务器页...
    99+
    2023-06-17
  • 前端CSS必须要学的知识点有哪些
    本文小编为大家详细介绍“前端CSS必须要学的知识点有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“前端CSS必须要学的知识点有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2024-04-02
  • Java开发中需要知道的基础知识有哪些
    这篇文章将为大家详细讲解有关Java开发中需要知道的基础知识有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Ja...
    99+
    2023-06-02
  • 前端必备的nginx知识点有哪些
    本篇内容主要讲解“前端必备的nginx知识点有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“前端必备的nginx知识点有哪些”吧!nginx简介Nginx是一款轻量级、高性能的 Web 服务...
    99+
    2023-07-05
  • vue项目前端知识点有哪些
    这篇文章将为大家详细讲解有关vue项目前端知识点有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。微信授权后还能通过浏览器返回键回到授权页在导航守卫中可以...
    99+
    2024-04-02
  • 可能不知道的sudo知识有哪些
    可能不知道的sudo知识有哪些,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。大家都知道 sudo,对吗?默认情况下,该工具已安装在大多数 Linux 系统上,并...
    99+
    2023-06-16
  • Linux shell中必须知道的知识有哪些
    本篇文章为大家展示了Linux shell中必须知道的知识有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。我个人很喜欢使用 Linux 系统,虽然说 Windows 的图形化界面做的确实比 Li...
    99+
    2023-06-16
  • node前端需了解的知识点有哪些
    这篇文章主要介绍“node前端需了解的知识点有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“node前端需了解的知识点有哪些”文章能帮助大家解决问题。基本特点快速了解nodejs可以从以下几个方...
    99+
    2023-07-05
  • PHP中必须知道的知识点有哪些
    这篇文章主要介绍“PHP中必须知道的知识点有哪些”,在日常操作中,相信很多人在PHP中必须知道的知识点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PHP中必须知道的知识点有哪些”的疑惑有所帮助!接下来...
    99+
    2023-06-20
  • 前端HTML必备基础知识有哪些
    本篇内容主要讲解“前端HTML必备基础知识有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“前端HTML必备基础知识有哪些”吧! Web服务本质 浏览器发...
    99+
    2024-04-02
  • web前端开发都需要学习哪些知识
    web前端开发在目前的IT行业是一个比较重要的岗位,web前端开发是直接与用户接触,前端体验的好坏,以及美观程度是非常重要的,毕竟现在是一个看脸的时代。前端开发需要学习的知识非常的多,非常的杂,一个前端页面的开发,需要涉及很多的知识,且前端...
    99+
    2023-06-03
  • web前端面试需要掌握哪些知识点
    本篇内容主要讲解“web前端面试需要掌握哪些知识点”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“web前端面试需要掌握哪些知识点”吧!  基本功考察  关于Html  1. html语义化标签的...
    99+
    2023-06-04
  • web前端的数据结构知识点有哪些
    本篇内容介绍了“web前端的数据结构知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1)什么叫算法?算法就是计算或解决问题的步骤。...
    99+
    2023-06-27
  • 前端Vue单元测试知识点有哪些
    本篇内容介绍了“前端Vue单元测试知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、为什么需要单元测试单元测试是用来测试项目中的...
    99+
    2023-06-22
  • jquery基础知识你知道哪些?
      jQuery.parent(expr) //找父元素  jQuery.parents(expr) //找到所有祖先元素,不限于父元素  jQuery.children(expr) //查找所有子元素,只会找到直接的孩子节点,不会返回所有...
    99+
    2023-06-03
  • Web前端必备基础知识点有哪些
    这篇文章主要介绍“Web前端必备基础知识点有哪些”,在日常操作中,相信很多人在Web前端必备基础知识点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Web前端必备基础知...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作