平庸前端碼農之蛻變 — AST

2021-02-12 前端瓶子君


前言

首先,先說明下該文章是譯文,譯文地址:https://juejin.im/post/5bfc21d2e51d4544313df666,原文出自《AST for JavaScript developers》。很少花時間特地翻譯一篇文章,咬文嚼字是件很累的事情,實在是這篇寫的太棒了,所以忍不住想和大家一起分享。

OK,我們直接進入正題。

為什麼要談AST(抽象語法樹)?

如果你查看目前任何主流的項目中的devDependencies,會發現前些年的不計其數的插件誕生。我們歸納一下有:javascript轉譯、代碼壓縮、css預處理器、elint、pretiier,等。有很多js模塊我們不會在生產環境用到,但是它們在我們的開發過程中充當著重要的角色。所有的上述工具,不管怎樣,都建立在了AST這個巨人的肩膀上。

所有的上述工具,不管怎樣,都建立在了AST這個巨人的肩膀上

我們定一個小目標,從解釋什麼是AST開始,然後到怎麼從一般代碼開始去構建它。我們將簡單地接觸在AST處理基礎上,一些最流行的使用例子和工具。並且,我計劃談下我的js2flowchart項目,它是一個不錯的利用AST的demo。OK,讓我們開始吧。

什麼是AST(抽象語法樹)?

It is a hierarchical program representation that presents source code structure according to the grammar of a programming language, each AST node corresponds to an item of a source code.

估計很多同學會和圖中的喵一樣,看完這段官方的定義一臉懵逼。OK,我們來看例子:

這很簡化

實際上,正真AST每個節點會有更多的信息。但是,這是大體思想。從純文本中,我們將得到樹形結構的數據。每個條目和樹中的節點一一對應。

那怎麼從純文本中得到AST呢?哇哦,我們知道當下的編譯器都做了這件事情。那我們就看看一般的編譯器怎麼做的就可以了。

想做一款編譯器是個比較消耗發量的事情,但幸運的是,我們無需貫穿編譯器的所有知識點,最後將高級語言轉譯為二進位代碼。我們只需要關注詞法分析和語法分析。這兩步是從代碼中生成AST的關鍵所在。

第一步,詞法分析,也叫做掃描scanner。它讀取我們的代碼,然後把它們按照預定的規則合併成一個個的標識tokens。同時,它會移除空白符,注釋,等。最後,整個代碼將被分割進一個tokens列表(或者說一維數組)。

當詞法分析原始碼的時候,它會一個一個字母地讀取代碼,所以很形象地稱之為掃描-scans;當它遇到空格,操作符,或者特殊符號的時候,它會認為一個話已經完成了。

第二步,語法分析,也解析器。它會將詞法分析出來的數組轉化成樹形的表達形式。同時,驗證語法,語法如果有錯的話,拋出語法錯誤。

當生成樹的時候,解析器會刪除一些沒必要的標識tokens(比如不完整的括號),因此AST不是100%與源碼匹配的,但是已經能讓我們知道如何處理了。說個題外話,解析器100%覆蓋所有代碼結構生成樹叫做CST(具體語法樹)

我們最終得到的

想要學習更多關於編譯器的知識?the-super-tiny-compiler,一個賊好的項目。大概200來行代碼,幾乎每行都有注釋。

想要自己創建門程式語言?LangSandbox,一個更好的項目。它演示了如何創造一門程式語言。當然,設計程式語言這樣的書市面上也一坨坨。所以,這項目上一個相比更加深入,與the-super-tiny-compiler的項目將Lisp轉為C語言不同,這個項目你可以寫一個你自己的語言,並且將它編譯成C語言或者機器語言,最後運行它。

我能直接用三方庫來生成AST嗎?

當然可以!有一坨坨的三方庫可以用。你可以訪問astexplorer,然後挑你喜歡的庫。astexplorer是一個很棒的網站,你可以在線玩轉AST,而且除了js,還有很多其它語言的AST庫。

我不得不強調一款我覺得很棒的三方庫,叫做babylon。

它被用在大名鼎鼎的babel中,也許這也是它之所以這麼火的原因。因為有babel項目的支持,我們可以意料到它將與時俱進,一直支持最新的JS特性,因此可以放心大膽地用,不怕以後JS又出新版導致代碼的大規模重構。另外,它的API也非常的簡單,容易使用。

Ok,現在你知道怎麼將代碼生成AST了,讓我們繼續,來看看現實中的用例。

第一個用例,我想談談代碼轉化,沒錯,就是那個貨,babel。

Babel is not a 『tool for having ES6 support』. Well, it is, but it is far not only what it is about.

經常把beble和支持es6/7/8聯繫起來,實際上,這也是我們經常用它的原因。但是,它僅僅是一組插件。我們也可以使用它來壓縮代碼,react相關語法轉譯(如jsx),flow插件等。

babel是一個javascript編譯器。宏觀來說,它分3個階段運行代碼:解析(parsing),轉譯(transforming),生成(generation)。我們可以給babel 一些javascript代碼,它修改代碼然後生成新的代碼返回。那它是怎樣修改代碼的呢?沒錯!它創建了AST,遍歷樹,修改tokens,最後從AST中生成新的代碼。

我們來從下面的demo中看下這個過程:

像我之前提到的,babel使用babylon,所以,首先,我們解析代碼成AST,然後遍歷AST,再反轉所有的變量名,最後生成代碼。完成!正如我們看到的,第一步(解析)和第三步(生成)看起來很常規,我們每次都會做這兩步。所以,babel接管處理了它倆。最後,我們最為關心的,那就是AST轉譯這一步了。

當我們開發babel-plugin的時候,我們只需要描述轉化你AST的節點「visitors」就可以了。

將它加入你的babel插件列表中,設置你webpack的babel-loader配置或者.babelrc中的plugins即可

如果你想要學習怎麼創建你的第一個babel-plugin,可以查看Babel-handbook

讓我們繼續,下一個用例,我想提到的是自動代碼重構工具,以及神器JSCodeshift。

比如說你想要替換掉所有的老掉牙的匿名函數,把他們變成Lambda表達式(箭頭函數)。

你的代碼編輯器很可能沒法這麼做,因為這並不是簡單地查找替換操作。這時候jscodeshift就登場了。

如果你聽過jscodeshift,你很可能也聽過codemods,一開始聽這兩個詞可能很困惑,不過沒關係,接下來就解釋。jscodeshift是一個跑codemods的工具。codemod是一段描述AST要轉化成什麼樣的代碼,這思想和babel的插件如出一轍。

所以,如果你想創建自動把你的代碼從舊的框架遷移到新的框架,這就是一種很乃思的方式。舉個例子,react 16的prop-types重構。

有很多不同的codemodes已經創建了,你可以保存你需要的,以免手動的修改一坨坨代碼,拿去揮霍吧:https://github.com/facebook/jscodeshifthttps://github.com/reactjs/react-codemod

最後一個用例,我想要提到Prettier,因為可能每個碼農都在日常工作中用到它。

Prettier 格式化我們的代碼。它調整長句,整理空格,括號等。所以它將代碼作為輸入,修改後的代碼作為輸出。聽起來很熟悉是嗎?當然!

思路還是一樣。首先,將代碼生成AST。之後依然是處理AST,最後生成代碼。但是,中間過程其實並不像它看起來那麼簡單。

同樣,如果你想學習更多在美化列印背後理論,這裡有一本你可以深入的書  《A prettier printer》。

文章迎來尾聲,我們繼續,今天最後一件事,我想提及的就是我的庫,叫做js2flowchart(4.5 k stars 在 Github)。

顧名思義,它將js代碼轉化生成svg流程圖

這是一個很好的例子,因為它向你展現了你,當你擁有AST時,可以做任何你想要做的事。把AST轉回成字符串代碼並不是必要的,你可以通過它畫一個流程圖,或者其它你想要的東西。

js2flowchart使用場景是什麼呢?通過流程圖,你可以解釋你的代碼,或者給你代碼寫文檔;通過可視化的解釋學習其他人的代碼;通過簡單的js語法,為每個處理過程簡單的描述創建流程圖。

馬上用最簡單的方式嘗試一下吧,去線上編輯看看 js-code-to-svg-flowchart

你也可以在代碼中使用它,或者通過CLI,你只需要指向你想生成SVG的文件就行。而且,還有VS Code插件(連結在項目readme中)

那麼,它還能做什麼呢?哇哦,我這裡就不廢話了,大家有興趣直接看這個項目的文檔吧。

OK,那它是如何工作的呢?

首先,解析代碼成AST,然後,我們遍歷AST並且生成另一顆樹,我稱之為工作流樹。它刪除很多不重要的額tokens,但是將關鍵塊放在一起,如函數、循環、條件等。再之後,我們遍歷工作流樹並且創建形狀樹。每個形狀樹的節點包含可視化類型、位置、在樹中的連接等信息。最後一步,我們遍歷所有的形狀,生成對應的SVG,合併所有的SVG到一個文件中。

結尾

尋找和篩選資料著實辛苦,希望同學們可以多多支持!

學習交流

相關焦點

  • 前端碼農之蛻變 — AST(抽象語法樹)
    前言首先,先說明下該文章是譯文,原文出自《AST for JavaScript developers》(https://itnext.io/ast-for-javascript-developers-3e79aeb08343)。很少花時間特地翻譯一篇文章,咬文嚼字是件很累的事情,實在是這篇寫的太棒了,所以忍不住想和大家一起分享。
  • AST抽象語法樹:最基礎的 Javascript 重點知識
    (給前端大全加星標,提升前端技能)作者:劉羽衝segmentfault.com/a/1190000016231512
  • 像玩 jQuery 一樣玩 AST
    本文來自飛豬前端的 @呦嘿 同學,萌妹子手把手教你使用 AST,這篇文章寫得很不錯值得一讀。這篇文章適合在原理性知識不通的情況下,仍然對 ast 蠢蠢欲動的開發者們,文章不具備任何專業性以及嚴謹性,它除了實用,可能一無是處。關於 AST 的介紹,網上已經一大堆了,不僅生澀難懂,還自帶一秒勸退屬性。
  • 查看Vue3 模板編譯後的 AST 和渲染函數
    我們通過在前面創建的項目 parcel 可做到零配置寫前端項目中添加這個 npm 包。<divid="suyan-app"><pclass="wrap"><h1>和素燕一起學前端{{ des }}</h1><ahref="http://lefex.gitee.io/">前端小課
  • 像玩 jQuery 一樣簡單地玩轉 AST
    🍭 魔法棒 之 趁手的工具🔗 AST exporer這是一個 ast 在線調試工具,有了它,我們可以非常直觀的看到 ast 生成前後以及代碼轉換,它分五個區域。我們接下來都依賴這個工具進行代碼操作。📖 魔法書 之 權威 api🔗 babel-typesast 語法字典,方便我們快速查閱結構樹的類型,它是我們想要通過 ast 生成某行代碼時的重要工具之一。認識 AST我以為的 AST
  • 前端開發聚合、分享、期刊訂閱類網站收集
    (PS:通過標籤管理,可以關注前端開發的相關內容)https://juejin.im/CSS Weekly一個概述最新的CSS文章,教程,工具和試驗的免費電子郵件周刊。http://css-weekly.com/奇舞周刊360前端,奇舞團博客整理的前端周刊,內容比較豐富,涵蓋最新的中文前端技術原創和翻譯文章以及最新資訊。
  • Web前端開發工資為什麼這麼高?非凡教育web設計培訓老師來解密
    特別是Web前端開發工程師,因為其高薪資、待遇好,成為當下比較熱門的職業。Web前端開發從事網際網路IT的人習慣性地被人稱之為「碼農」,碼農這個詞有點戲謔的味道,在印象裡,碼農格子襯衫、雙肩包、不太注重形象和外表,而且bug從不離嘴,今天非凡教育
  • 小白如何學習web前端開發知識
    在掌握基礎模塊的基礎上,Web前端工程師還必須進一步將技能層次化、系統化,從而能夠視線頁面架構、移動頁面開發等等任務。不僅新人小白需要努力,就連已經入職0~3年的前端開發工程師,也需要不斷學習了解前端高階知識和技能,不斷修煉自身武功。
  • 【第2134期】前端工程師是如何做「資損防控」的?
    探索之路在資損防控方面,服務端比前端起步要早,而且做得也非常專業,比如各種離線或實時的容災冪等檢查、鏈路對帳告警、關鍵配置巡檢、關鍵標巡檢等等。應用層:訂閱權益的對帳消息並打通實時報警流程,以及通過 SLS 日誌,查看權益的實時大盤以及模塊治理。
  • 所謂平庸之惡……
    哪怕這件事根本與之毫無關聯,哪怕他們抨擊的角度是如何無理和刁鑽。就像此次新聞事件,女孩僅僅是去過酒吧,竟然就因此成為了眾矢之的。真是俗話所說的:欲加之罪,何患無辭?03平庸之惡德國思想家漢娜·阿倫特曾經提出,在某些世界裡更廣泛地存在著一種「平庸無奇的惡」。
  • 論前端技術和前端工程之辯
    正文什麼是前端技術?如果有前端開發技術, 前端研發技術與應用這樣的學科, 你覺得會包含哪些內容?因為我也是常年業務團隊出身, 我一直在思索破局之法, 我相信佔據了 90% 前端工程師精力的事情不可能是這種毫無意義註定走下坡路的工作, 這裡一定有啥是不對的. 或者不科學的.
  • 平庸之惡的根源在哪裡
    平庸之惡,英文為The Banality of Evil,由猶太裔著名政治思想家漢娜·阿倫特提出。這一概念幫助去除了人們對「惡」的神秘感。它讓人們看到,這樣的惡是平庸的,是不思考,不思考人,不思考社會,可以發生在每一個人身上。不識數、不知道、不靠譜,林林總總的怪現狀體現的是一種平庸之惡。在平時只是不給力,但是關鍵時刻真是耽誤事,甚至傷士氣。
  • 江蘇高考作文題「拒絕平庸」被指催生大批平庸之作
    在場專家普遍認為:今年的《拒絕平庸》將會出現一大批平庸之作。實習生 楊甜子本報記者 王 璟攝影 吳 俊最讓考生撓頭的四大問題疑問一:為什麼要拒絕「平庸」?專家觀點:是考題混淆了「平庸」的概念出場專家: 凌煥新(南京師範大學教授、省寫作學會會長)對於「拒絕平庸」,首先要弄懂一個概念:拒絕平庸,首先什麼是「平庸」?在現代漢語辭典中,「平凡」和「平庸」是近義詞,甚至於某些方面帶有一點重疊的意義。
  • 漢娜·阿倫特:平庸之惡
    是的,當一次次令人痛心的社會新聞曝光之後,我們不得不重新思考一下20世紀唯一堪稱最偉大哲學家的漢娜·阿倫特(HannahArendt)著名的「平庸之惡」:這種惡,是不思考。不思考人,不思考社會。惡是平庸的,因為你我常人,都可能墮入其中。
  • 2020大廠前端面試之vue專題
    將結果返回給前端,頁面重新渲染。MVVM :傳統的前端會將數據手動渲染到頁面上, MVVM 模式不需要用戶收到操作 dom 元素,將數據綁定到 viewModel 層上,會自動將數據渲染到頁面中,視圖變化會通知 viewModel層 更新數據。ViewModel 就是我們 MVVM 模式中的橋梁.
  • 沒人覺得碼農的job security很差嗎?碼農就是吃青春飯?!引發一場巨大爭議…
    相比於所謂的傳統行業,我寧願冒風險當碼農每年拿幾倍的工資。@qqaas :我的感受跟你不太一樣!@qwseda123 : 能讓你用醫生和律師來做對比 這本身就是一種碼農的勝利。醫生律師 vs 碼農 門檻是一樣的麼?門檻不同不能對比啊。我做碼農不是因為我不想做醫生律師,是因為他們門檻高 ,入學門檻高執業門檻高,千軍萬馬過了獨木橋必須要保證安穩,否則誰去吃這個苦。
  • 細數國內外前端大牛的知乎與博客
    相關連結github https://github.com/RubyLouvre知乎 https://www.zhihu.com/people/si-tu-zheng-mei微博 http://weibo.com/jslouvre樸靈簡介《深入淺出Node.js》作者,大牛,真名田永強,文藝型碼農
  • 月入五萬的碼農,搶了文科生的飯碗
    結果美國的碼農以78.0的總分排第28名,軟體服務大國印度則以76.0的總分排第31名,而參與這一次編程競賽的程式設計師中,美國和印度程式設計師相對最多。中國程式設計師排名第一,得了基準分的100.0分,那些水平高的碼農通常來自數學教育水準高的地區,如東歐和東亞地區。
  • 30歲學前端開發來得及嗎,好找工作麼
    前端開發30歲學前端開發還得來得及嗎,好找工作嗎?這個問題應該是很多轉行者比較想要了解的,其實可以從三個問題來入手剖析解答。問題一:30歲學前端開發還得來得及嗎?很多人說當年齡在30-35歲,是人在職場發展的分水嶺,它不僅決定著一個人能在職場上走多遠,更決定著你在人生下半場是優秀還是平庸。有網友說,年齡不是問題,我身邊就有30多歲,轉學前端開發,關鍵看自己。
  • 00後AI明日之星扎堆AI;用碼農冒充AI寫代碼;I實時篩查癌細胞
    清華今日開學!松寶有話說:00後明日之星投身計算機AI,希望中國計算機AI發展更前沿。2.【業界 | AI大造假!一明星公司用印度碼農冒充AI,騙取超2億融資】來源: DeepTech一明星公司用印度碼農冒充AIAI 取代「碼農」還沒實現,卻有公司大開腦洞反向操作,用碼農冒充 AI。一家名為 Engineer.ai 的印度創業公司就是這麼幹的,他們聲稱用 AI 技術來編寫代碼,使每個人都能夠構建和運行定製軟體。