JavaScrpit AST实战

栏目: IT技术 · 发布时间: 3年前

内容简介:每个编程语言都有自己的AST,了解AST并能进行一些开发,会给我们的项目开发提供很大的便利。下面就带大家一探究竟AST也就是抽象语法树。简单来说就是把程序用树状形式展现。每种语言(HTML,CSS,JS等)都有自己的AST,而且还有多种AST解析器。

前言

每个编程语言都有自己的AST,了解AST并能进行一些开发,会给我们的项目开发提供很大的便利。下面就带大家一探究竟

通过本文能了解到什么

1. JS AST结构和属性 2. babel插件开发

JS AST简介

AST也就是抽象语法树。简单来说就是把程序用树状形式展现。每种语言(HTML,CSS,JS等)都有自己的AST,而且还有多种AST解析器。

回归JS本身,常见的AST解析器有:

acorn @babel/parser Typescript Uglify-js 等等

为什么会有多种解析器?

JS AST并没有一个统一的规范。各家AST解析器都是为内部提供服务。所以有各自的解析器也就不难理解了。虽然不同解析器解析出来的AST在结构上有些许差异,但本质上类似。 本文将基于@babel/parser来进行示例和讲解

下面来看一句常见的代码

import ajax from 'axios'

转换后的AST结构如下:

{

"type": "ImportDeclaration",

"start": 0,

"end": 21,

"loc": {

"start": {

"line": 1,

"column": 0

},

"end": {

"line": 1,

"column": 21

}

},

"specifiers": [

{

"type": "ImportDefaultSpecifier",

"start": 7,

"end": 10,

"loc": {

"start": {

"line": 1,

"column": 7

},

"end": {

"line": 1,

"column": 10

}

},

"local": {

"type": "Identifier",

"start": 7,

"end": 10,

"loc": {

"start": {

"line": 1,

"column": 7

},

"end": {

"line": 1,

"column": 10

},

"identifierName": "Vue"

},

"name": "Vue"

}

}

],

"importKind": "value",

"source": {

"type": "StringLiteral",

"start": 16,

"end": 21,

"loc": {

"start": {

"line": 1,

"column": 16

},

"end": {

"line": 1,

"column": 21

}

},

"extra": {

"rawValue": "vue",

"raw": "'vue'"

},

"value": "vue"

}

}


内容是不是比想象的多?莫慌,我们一点一点看。来一张简略图: JavaScrpit AST实战

ImportDeclaration

语句的类型,表明是一个import的声明。常见的有:

  • VariableDeclaration:var x = 'init'

  • FunctionDeclaration:function func(){}

  • ExportNamedDeclaration:export function exp(){}

  • IfStatement:if(1>0){}

  • WhileStatement:while(true){}

  • ForStatement:for(;;){}

  • 不一一列举

既然是一个引入表达式,自然分左右两部分,左边的是specifiers,右边的是source

specifiers

specifiers节点会有一个列表来保存specifier

  • 如果左边只声明了一个变量,那么会给一个ImportDefaultSpecifier

  • 如果左边是多个声明,就会是一个ImportSpecifier列表。

什么叫左边有多个声明?看下面的示例

import {a,b,c} from 'X' 

变量的声明要保持唯一性 而Identifier就是鼓捣这个事情的

source

source包含一个字符串节点StringLiteral,对应了引用资源所在位置。示例中就是axios

AST是如何转换出来的呢?

以babel为例子:

const parser = require('@babel/parser')

let codeString = `

import ajax from 'axios'

`;


let file = parser.parse(codeString,{

sourceType: "module"

})

console.dir(file.program.body)

在node里执行一下,就能打印出AST 通过这个小示例,大家应该对AST有个初步的了解,下面我们谈谈了解它有什么意义

应用场景以及实战

实际上,我们在项目中,AST技术随处可见

  • Babel对es6语法的转换

    让我们可以提前使用浏览器不支持的语法。babel通过AST将语法进行转换

  • Webpack对依赖的收集

    webpack在编译时,会从入口开始收集所有的依赖。而对依赖的判定也是基于AST的

  • 组件库的按需加载babel-plugin

    典型的就是各个组件库的按需加载,比如element-ui的按需加载babel-plugin

  • 等等

为了更好的理解AST,我们定义一个场景,然后实战一下。

场景:把import转换成require,类似于babel的转换

目标:通过AST转换,把语句

import ajax from 'axios'

转为

var ajax = require('axios')

要达到这个效果,首先我们要写一个babel-plugin。先上代码 babelPlugin.js代码如下:

const t = require('@babel/types');


module.exports = function babelPlugin(babel) {



function RequireTranslator(path){


var node = path.node

var specifiers = node.specifiers


//获取变量名称

var varName = specifiers[0].local.name;

//获取资源地址

var source = t.StringLiteral(path.node.source.value)

var local = t.identifier(varName)

var callee = t.identifier('require')

var varExpression = t.callExpression(callee,[source])

var declarator = t.variableDeclarator(local, varExpression)

//创建新节点

var newNode = t.variableDeclaration("var", [declarator])

//节点替换

path.replaceWith(newNode)


}


return {


visitor: {

ImportDeclaration(path) {

RequireTranslator.call(this,path)

}


}

};

};


测试代码:

const babel = require('@babel/core');

const babelPlugin = require('./babelPlugin')


let codeString = `

import ajax from 'axios'

`;


const plugins = [babelPlugin]


const {code} = babel.transform(codeString,{plugins:plugins});


console.dir(code)

输出结果:

'var ajax = require("axios");'

目标达成!

babel-plugin 

在babel的官网有开发文档,这里只是简单的描述一下注意要点:

插件要求返回一个visitor对象。 可以拦截所有的节点,函数名称就是节点类型,入参是path,可以通过path.node来获取当前节点 @babel/types提供了大量节点操作的API,同样可以在官网看的详细的说明 transform  这里的代码大家是不是看着很熟悉。 没错,就是.babelrc里的配置。我们开发的插件,配置到.babelrc的plugins里,就可以全局运行了。

写在最后

JS的AST,给我们提供了实现各种可能的机会。我们可以自定义一个语法,可以将组件的按需引入过程简化等等。同时不仅仅是JS,CSS,HTML,SQL等语言都可以在ast语法级别去进行一些有趣的操作。该篇文章只是带大家简单入门。

前端不仅仅是UI,可玩的东西还有很多


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP程序设计

PHP程序设计

Kevin Tatroe、Rasmus Lerdorf / 邓云佳 / 中国电力出版社 / 2003-7-1 / 68.00

本书涵盖了创建一个高效PHP Web应用程序所需要的所有技术,其内容包括:PHP语言基础的详细信息,包括数据类型、变量、操作符和流控制语句。用专门章节讨论关于函数、字符串、数组和对象的基本内容。涵盖通用的PHP Web应用程序设计技术,如表单处理和验证、会话跟踪以及cookie。用和数据库无关的PEAR DB库与关系数据库(如MySQL和Oracle)进行交互的内容。介绍用PHP生成动态图像、创建一起来看看 《PHP程序设计》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具