成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

沒(méi)有AST, IDE中的錯(cuò)誤提示、自動(dòng)補(bǔ)全、重構(gòu)、語(yǔ)法檢查......都玩不轉(zhuǎn)了

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

[[257628]]

 張大胖一上班,領(lǐng)導(dǎo)就扔了一個(gè)任務(wù)給他,把項(xiàng)目中的JavaScript代碼做點(diǎn)“小小”的改變:

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

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

對(duì)不熟悉JS的同學(xué)稍微解釋一下:

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

parseInt(a,10) 表示以十進(jìn)制的方式來(lái)解析。

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

對(duì)***個(gè)任務(wù): 找到'==',替換成'==='就行 。

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

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

有沒(méi)有別的辦法?

01抽象語(yǔ)法樹(shù)

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

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

張大胖想起來(lái)自己沒(méi)有考及格的《編譯原理》,里邊講到了抽象語(yǔ)法樹(shù)(AST)不就是所謂結(jié)構(gòu)化的東西嗎?

比如表達(dá)式 result = 6+7*3 , 用抽象語(yǔ)法樹(shù)來(lái)表示就是:

 

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


 

但是這其中有三個(gè)問(wèn)題:

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

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

2. 如何遍歷這個(gè)AST,來(lái)修改這顆樹(shù)的枝枝葉葉?

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

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

張大胖趕緊打開(kāi)Google 搜索,很快便找到了三個(gè)開(kāi)源的工具,正好完成對(duì)應(yīng)的三個(gè)功能:

esprima : 從JavaScript源代碼形成AST

estraverse:遍歷樹(shù)的節(jié)點(diǎn)并修改

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

02創(chuàng)建AST

說(shuō)干就干,張大胖準(zhǔn)備了一段代碼來(lái)做實(shí)驗(yàn):

  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)化成了抽象語(yǔ)法樹(shù)。

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

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

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

 

03遍歷修改AST

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

  1. //JS語(yǔ)法樹(shù)遍歷各節(jié)點(diǎn) 
  2. const estraverse = require('estraverse'); 
  3. //從JS語(yǔ)法樹(shù)生成源代碼 
  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.     }); 

這個(gè)函數(shù)負(fù)責(zé)把‘==’改成‘===’

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

這個(gè)函數(shù)負(fù)責(zé)把parseInt改成標(biāo)準(zhǔn)調(diào)用:

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

經(jīng)過(guò)這個(gè)函數(shù),原來(lái)的 if (parseInt(age) >= 18) 就變成了下圖這樣,相當(dāng)于增加了一個(gè)節(jié)點(diǎn),對(duì)應(yīng)的代碼就是 :if (parseInt(age,10) >= 18)

 

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

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

通過(guò)這個(gè)實(shí)驗(yàn),張大胖基本上了解了AST的原理和用法,接下來(lái)可以著手正式的編程了。

04總結(jié)

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

JavaScript代碼語(yǔ)法、風(fēng)格的檢查

在IDE中的錯(cuò)誤提示、自動(dòng)補(bǔ)全,重構(gòu)

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

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

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

 

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

責(zé)任編輯:武曉燕 來(lái)源: 51CTO
相關(guān)推薦

2012-12-24 09:54:06

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

2013-01-10 12:50:38

移動(dòng)游戲人才

2020-11-20 11:02:26

AST函數(shù)Javascript

2022-01-18 18:46:55

Eslint抽象語(yǔ)法樹(shù)Babel

2009-12-09 10:46:06

PHP檢查語(yǔ)法錯(cuò)誤

2009-07-17 14:55:38

ibatis官方

2014-05-15 11:02:34

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

2021-09-14 11:10:20

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

2009-06-03 17:00:08

Eclipse自動(dòng)補(bǔ)全

2017-07-04 15:07:44

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

2020-12-08 06:20:49

前端重構(gòu)Vue

2022-12-26 00:02:24

重構(gòu)代碼軟件

2020-07-31 07:44:12

代碼自動(dòng)補(bǔ)全

2024-05-10 08:51:31

Python命令補(bǔ)全工具

2017-06-05 14:27:56

MyCLIMySQLMariaDB

2022-01-13 14:06:37

Python 開(kāi)發(fā)編程語(yǔ)言

2024-11-11 00:38:13

Mypy靜態(tài)類型

2014-12-31 17:12:54

模糊查詢模糊查詢

2011-04-20 08:55:17

BlackBerry

2016-12-20 09:30:22

shell腳本linux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 午夜视频在线 | 国产超碰人人爽人人做人人爱 | 91精品国产乱码久久久久久久久 | 精品一区二区三区四区视频 | 老司机67194精品线观看 | 亚洲国产欧美在线 | 一区二区成人在线 | 欧美 日韩 在线播放 | 色婷婷精品国产一区二区三区 | 亚洲国产视频一区二区 | 国产亚洲一区二区三区 | 免费观看一级黄色录像 | 在线不卡一区 | 91最新视频 | 男女国产视频 | 国产福利91精品 | 综合久久亚洲 | 久久久精品一区二区三区 | 精品久久久av | 不卡的av在线 | 国产激情网站 | 久热久| 久久99精品久久久久久 | 91免费看片 | 国产观看 | 99精品在线| 亚州精品天堂中文字幕 | 欧美成人a | 日韩中文字幕在线视频观看 | 亚洲黄色片免费观看 | 精品国产一区二区三区四区在线 | 日韩在线精品视频 | 亚洲欧美一区二区在线观看 | 日韩精品久久久久久 | 欧美久久久久久久久 | 久久国产视频网 | 国产真实乱全部视频 | 99精品国自产在线 | 毛片.com| 一区不卡在线观看 | www精品 |