自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

沒有AST, IDE中的錯誤提示、自動補全、重構、語法檢查......都玩不轉(zhuǎn)了

開發(fā) 開發(fā)工具
如果能把JavaScript源碼轉(zhuǎn)化成結構化的對象,就可以精確地知道一段代碼中有哪些變量名,函數(shù)名,參數(shù)...... 這樣就可以寫程序就可以進行處理了。

[[257628]]

 張大胖一上班,領導就扔了一個任務給他,把項目中的JavaScript代碼做點“小小”的改變:

1. 把 == 改為全等 ===

2. 把parsetInt不標準的調(diào)用改為標準用法 parseInt(xxx)-> parseInt(xxx,10)

對不熟悉JS的同學稍微解釋一下:

JS在比較兩個變量的時候,雙等號將執(zhí)行類型轉(zhuǎn)換; 三等號將進行相同的比較,而不進行類型轉(zhuǎn)換 (如果類型不同, 只是總會返回 false );

parseInt(a,10) 表示以十進制的方式來解析。

對于這些任務,張大胖腦海中馬上閃現(xiàn)出了解決辦法:字符串替換。

對***個任務: 找到'==',替換成'==='就行 。

對第二個任務: parseInt(xxx) 改成parseInt(xxx,10), 沒法直接替換,得寫個正則表達式,找到那些只有一個參數(shù)的parseInt字符串,然后加上一個新的參數(shù):10 。

張大胖對自己的正則表達式能力不太自信,如果考慮得不周全,代碼就可能被改壞了。

有沒有別的辦法?

01抽象語法樹

使用正則表達式,只能把JavaScript源代碼當做文本來處理,能力很弱,無法觸及到JavaScript的語法層面,正則表達式?jīng)]法知道這個地方是變量,那個地方是函數(shù)名.....

如果能把JavaScript源碼轉(zhuǎn)化成結構化的對象,就可以精確地知道一段代碼中有哪些變量名,函數(shù)名,參數(shù)...... 這樣就可以寫程序就可以進行處理了。

張大胖想起來自己沒有考及格的《編譯原理》,里邊講到了抽象語法樹(AST)不就是所謂結構化的東西嗎?

比如表達式 result = 6+7*3 , 用抽象語法樹來表示就是:

 

如果把所有的JavaScript代碼都轉(zhuǎn)化成這樣一顆AST的樹,那代碼的一切都盡在掌握, 可以任意修改了。


 

但是這其中有三個問題:

1. 怎么從文本形式的源代碼形成這么一個AST ?

讓自己寫程序?qū)崿F(xiàn)那就太難了,得做詞法分析,語法分析等等。

2. 如何遍歷這個AST,來修改這顆樹的枝枝葉葉?

比如我想在AST這棵樹中添加一個新的節(jié)點,該怎么做?

3. 修改完成以后,怎么再次把AST變成文本的源代碼?

張大胖趕緊打開Google 搜索,很快便找到了三個開源的工具,正好完成對應的三個功能:

esprima : 從JavaScript源代碼形成AST

estraverse:遍歷樹的節(jié)點并修改

escodegen : 把修改完的AST再次轉(zhuǎn)化為源代碼。

02創(chuàng)建AST

說干就干,張大胖準備了一段代碼來做實驗:

  1. //源碼 
  2. function fun1(opt) { 
  3.     if (opt.status == 1) { 
  4.         console.log('1'); 
  5.     } 
  6.     if (opt.status == 2) { 
  7.         console.log('2'); 
  8.     } 
  9. function fun2(age) { 
  10.     if (parseInt(age) >= 18) { 
  11.         console.log('ok 你已經(jīng)成年'); 
  12.     } 

使用esprima,輕輕松松就把它轉(zhuǎn)化成了抽象語法樹。

  1. //JS語法樹模塊 
  2. const esprima = require('esprima'); 
  3. //創(chuàng)建AST 
  4. const AST = esprima.parseScript(jsCode); 

(由于轉(zhuǎn)成樹后結構非常大,這里不再展示了, 感興趣的同學自己可以到http://esprima.org/demo/parse.html 去玩一把, 很有趣。 )

比如: if (parseInt(age) >= 18) 這一句,就被轉(zhuǎn)化成了這樣:

 

03遍歷修改AST

有了AST,就可以就是遍歷和修改了,還是使用開源的工具。

  1. //JS語法樹遍歷各節(jié)點 
  2. const estraverse = require('estraverse'); 
  3. //從JS語法樹生成源代碼 
  4. const escodegen = require('escodegen'); 
  5.  
  6. function walkIn(ast){ 
  7.     estraverse.traverse(ast, { 
  8.         enter: (node) => { 
  9.             toEqual(node);//把 == 改為全等 === 
  10.             setParseInt(node); //parseInt(a)-> parseInt(a,10) 
  11.         } 
  12.     }); 

這個函數(shù)負責把‘==’改成‘===’

  1. function toEqual(node) { 
  2.     if (node.operator === '==') { 
  3.         node.operator = '==='
  4.     } 

這個函數(shù)負責把parseInt改成標準調(diào)用:

  1. function setParseInt(node) { 
  2.     //判斷節(jié)點類型 方法名稱,方法的參數(shù)的數(shù)量,數(shù)量為1就增加第二個參數(shù)。 
  3.     if (node.type === 'CallExpression' && node.callee.name === 'parseInt' && node.arguments.length===1){ 
  4.         node.arguments.push({//增加參數(shù),其實就是數(shù)組操作 
  5.             "type""Literal"
  6.             "value": 10, 
  7.             "raw""10" 
  8.         }); 
  9.     } 

經(jīng)過這個函數(shù),原來的 if (parseInt(age) >= 18) 就變成了下圖這樣,相當于增加了一個節(jié)點,對應的代碼就是 :if (parseInt(age,10) >= 18)

 

***使用escodegen 把修改過的AST再次變成源代碼,就大功告成了:

  1. //生成目標代碼 
  2. const code = escodegen.generate(ast); 
  3. //寫入文件..... 
  4. //....你懂的 

通過這個實驗,張大胖基本上了解了AST的原理和用法,接下來可以著手正式的編程了。

04總結

本文的例子用AST也許不是***解, 主要是為了展示AST的處理技術, AST實際上就是源代碼的一種結構化表示, 利用它及相關工具可以方便地優(yōu)化和修改代碼,只要是你能對這棵“AST樹”做“修剪”就可以對源代碼做各種“手腳”:

JavaScript代碼語法、風格的檢查

在IDE中的錯誤提示、自動補全,重構

代碼的壓縮和混淆 代碼的轉(zhuǎn)換 ......

有這么強大的功能,AST處理技術是很多知名工具的基礎, 例如babel,webpack,還有jd taro等都把AST用得***。

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請通過作者微信公眾號coderising獲取授權】

 

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO
相關推薦

2012-12-24 09:54:06

大數(shù)據(jù)數(shù)據(jù)科學家

2020-11-20 11:02:26

AST函數(shù)Javascript

2009-12-09 10:46:06

PHP檢查語法錯誤

2013-01-10 12:50:38

移動游戲人才

2022-01-18 18:46:55

Eslint抽象語法樹Babel

2009-07-17 14:55:38

ibatis官方

2009-06-03 17:00:08

Eclipse自動補全

2014-05-15 11:02:34

Linux操作系統(tǒng)國產(chǎn)操作系統(tǒng)

2021-09-14 11:10:20

程序員技能開發(fā)者

2017-07-04 15:07:44

Windows 7Windows數(shù)據(jù)錯誤

2020-12-08 06:20:49

前端重構Vue

2020-07-31 07:44:12

代碼自動補全

2024-05-10 08:51:31

Python命令補全工具

2017-06-05 14:27:56

MyCLIMySQLMariaDB

2022-01-13 14:06:37

Python 開發(fā)編程語言

2022-12-26 00:02:24

重構代碼軟件

2014-12-31 17:12:54

模糊查詢模糊查詢

2016-12-20 09:30:22

shell腳本linux

2020-03-20 10:13:15

Linux 系統(tǒng) 數(shù)據(jù)

2024-11-11 00:38:13

Mypy靜態(tài)類型
點贊
收藏

51CTO技術棧公眾號