我搜尋了很多馴服JAVAScript的工具,結(jié)果發(fā)現(xiàn)了它
3主流,2晦澀,1在上升
> Photo by Anna Elfimova on Unsplash
我已經(jīng)使用靜態(tài)類型語言進(jìn)行編碼多年,從Assembler開始,通過Visual Basic和C#遷移到C,但是當(dāng)我遷移到JavaScript時(shí),對(duì)軟件的所有理解都發(fā)生了變化。
我的JavaScript初體驗(yàn)
當(dāng)我決定第一次嘗試JavaScript時(shí),我使用Sublime Text進(jìn)行了編碼,這全都與文本編輯,多光標(biāo),微插件有關(guān),并且與Visual Studio相比,它的運(yùn)行速度極快。 我不必等待IntelliSense或編譯器,我鍵入,保存并準(zhǔn)備好運(yùn)行代碼了,瞧!
腳本語言的速度非常快,但也發(fā)生了一點(diǎn)變化:每小時(shí)我的手指可能輸入的錯(cuò)誤數(shù)量激增。
我喜歡C#,也喜歡IDE,Intellisense,自動(dòng)完成功能,并且誠實(shí)地使用了"面向編譯器的開發(fā)"。 我只是通過閱讀出現(xiàn)錯(cuò)誤時(shí)編譯器和Intellisense指出的內(nèi)容來學(xué)習(xí)的。
正如您現(xiàn)在可能想到的那樣,我很快就從靜態(tài)類型化和編譯型語言中獲得了JavaScript的優(yōu)勢(shì):語法很怪異,沒有任何東西可以緩存我的錯(cuò)誤,當(dāng)時(shí)的范圍很混亂,庫缺乏自動(dòng)發(fā)現(xiàn)能力(沒有Intellisense), 承諾不存在,并且框架沒有像今天那樣被采用。
我的第一個(gè)框架
在我最初使用JavaScript多年后,雖然主要使用C#,但是我找到了一份可以全職使用AngularJS的工作。 我感到AngularJS使項(xiàng)目更加結(jié)構(gòu)化,并為JavaScript帶來了編程中常見的"良好實(shí)踐"。
在2年的時(shí)間里,該項(xiàng)目使我吸取了許多關(guān)于JavaScript的經(jīng)驗(yàn),但是我仍然覺得沒有什么能像我預(yù)期的那樣順利進(jìn)行。
無法馴服的JavaScript
我覺得JavaScript難以馴服:運(yùn)行時(shí)異常仍然是一種規(guī)范,我的大多數(shù)代碼在大多數(shù)時(shí)間都重復(fù)了,可讀性仍然是一個(gè)問題,表達(dá)意圖不僅是挑戰(zhàn),而且是奢侈,我過去編程中的知識(shí)很少 經(jīng)驗(yàn)似乎在JavaScript中效果很好,而最糟糕的部分是:我仍然覺得自己是一個(gè)糟糕的JavaScript程序員。
在嘗試將我的面向?qū)ο蟪绦蛟O(shè)計(jì)知識(shí)以及其他從C#到JavaScript的優(yōu)秀知識(shí)應(yīng)用于我時(shí),我一直關(guān)注著一切如何轉(zhuǎn)變,這花了我一段時(shí)間,但直到最后,我決定改變思路。
取消一切
我進(jìn)入了一個(gè)新的狀態(tài),我的前提是:將面向?qū)ο蟮木幊淘砗驮O(shè)計(jì)模式應(yīng)用于JavaScript是浪費(fèi)時(shí)間,JavaScript并非完全為此目的而設(shè)計(jì),我將盡我所能來做事情 忘了OOP。
我開始積累自己的一套良好實(shí)踐,一段時(shí)間后,我開始覺得自己對(duì)JavaScript有所了解。 最后,我開始減少代碼編寫,減少錯(cuò)誤,做出有用的抽象,一切開始看起來不錯(cuò),與此同時(shí),我遇到了有關(guān)……函數(shù)式編程的文字。
函數(shù)式編程
吞噬了關(guān)于函數(shù)式編程的所有知識(shí)之后,我設(shè)法將我的每一個(gè)良好的JavaScript做法都映射到一個(gè)函數(shù)式編程概念,但是函數(shù)式編程不僅囊括了我的全部經(jīng)驗(yàn),而且這超出了我最瘋狂的夢(mèng)想。
我開始應(yīng)用并展示每個(gè)概念的每一個(gè)提交,菜鳥的錯(cuò)誤,我的團(tuán)隊(duì)完全不了解我們已經(jīng)使用OOP近兩年了,使用AngularJS,在項(xiàng)目結(jié)束時(shí)轉(zhuǎn)移范例肯定會(huì)死, 我更正并繼續(xù)使用OOP。 幸運(yùn)的是,該項(xiàng)目結(jié)束了,我可以進(jìn)入一個(gè)新的職位,這個(gè)新職位使團(tuán)隊(duì)擁有更多的函數(shù)式編程經(jīng)驗(yàn)。
在工作之間,我練習(xí)了函數(shù)式編程,并試圖發(fā)現(xiàn)如何使用每個(gè)可用的庫。 我終于感覺到對(duì)JavaScript的控制了,要獲得對(duì)JavaScript的控制,我不得不放棄它。
放棄JavaScript
在學(xué)習(xí)了函數(shù)式編程的一些基礎(chǔ)知識(shí)之后,我決定嘗試使用比AngularJS更適合FP的其他框架(此時(shí)Angular 2已經(jīng)存在了)。
我開始使用現(xiàn)代框架,遇到了React和Elm,我愛Elm! 那TypeScript呢? 盡管我完全放棄了windows,但我不敢相信我很高興再次使用Microsoft工具。 這是我所需要的全部時(shí)間。
回想起來,以自己的方式嘗試之后,我絕對(duì)可以確定,我對(duì)JavaScript的不良表現(xiàn)的很大一部分是我自己對(duì)工具的缺乏了解,而這些工具與我對(duì)軟件的自然思考方式更為相關(guān),因此我感覺自己像 在使用公司的技術(shù)堆棧時(shí)從水中撈出。
在給我當(dāng)前的工具鏈之前,有一條建議:沒有限制地自己練習(xí)要掌握的語言,然后再找到與您的喜好相匹配的工作,否則,您可能會(huì)感到痛苦,因?yàn)?您將為自己使用錯(cuò)誤的工具,因此永遠(yuǎn)無法發(fā)揮自己的潛力。
我的JavaScript工具鏈
您肯定知道其中一些工具,但是為了完整起見,我將嘗試對(duì)所有這些工具進(jìn)行簡要說明。
> Banner from TypeScript home page
TypeScript
在他們自己的主頁上:
TypeScript是JavaScript的類型化超集,可編譯為純JavaScript。
是什么讓我在每個(gè)項(xiàng)目中都使用TypeScript?
編譯錯(cuò)誤
在編譯時(shí)發(fā)現(xiàn)錯(cuò)誤是一件好事,這需要幾秒鐘嗎? 值得。 愚蠢的錯(cuò)誤,莫名其妙的運(yùn)行時(shí)錯(cuò)誤,顯示得太遲的錯(cuò)誤的無奈使我對(duì)這個(gè)職業(yè)的熱愛減少了,但是TypeScript再次帶來了歡樂。
類型
表現(xiàn)力和順從性,意圖和統(tǒng)一性,設(shè)計(jì)和力量,類型需要時(shí)間來掌握,但是孩子們,他們值得。 每一個(gè) 單。 時(shí)間。 我非常想念類型。 TypeScript和函數(shù)型都兼容面向?qū)ο蟮念愋汀?/p>
當(dāng)您有類型時(shí),很多對(duì)話消失了,您為試圖理解和使用代碼的人們節(jié)省了很多時(shí)間,無需閱讀手冊(cè)就可以發(fā)現(xiàn)整個(gè)庫的使用,并且可以確保一切都會(huì) 由于類型約束而應(yīng)該使用。
TypeScript中的類型還有很長的路要走,但是今天的類型系統(tǒng)已經(jīng)為前端帶來了如此強(qiáng)大的功能。 沒有類型系統(tǒng)感覺就像試圖步行超越賽車。 它給人以JavaScript錯(cuò)過的工程感,我使用類型來設(shè)計(jì)和強(qiáng)制正確使用接口,并且每天花我安全的時(shí)間編寫類型(好吧,這主要是我的看法)。
減輕我的挫敗感
有了TypeScript,我每小時(shí)的錯(cuò)誤以及因此而感到沮喪的機(jī)會(huì)大大減少了,僅此部分就值得了。
該版本的TypeScript也越來越好,它迅速采用了新的ECMAScript功能。
因此,是的,我放棄了使用純?cè)糐avaScript編寫代碼的方式,這對(duì)我的理智有危害。 TypeScript具有JavaScript的所有優(yōu)點(diǎn)以及許多使JavaScript實(shí)際可行的機(jī)制。
> Banner from @code Twitter
Visual Studio Code
這不是IDE,而是文本編輯器,是其主頁上最好的文本前端編輯器:
代碼編輯。 重新定義。 自由。 建立在開源上。 無處不在。
為什么選擇VSCode?
無處不在
這句話是正確的,我已經(jīng)在需要使用的每個(gè)操作系統(tǒng)上可靠地使用了VSCode,它速度很快,并且在所有地方都有很多優(yōu)點(diǎn),無需擔(dān)心平臺(tái)支持。
智能感知
Yeeeesss。 它可以使用JavaScript創(chuàng)造奇跡,但是使用TypeScript,它就像上帝一樣,快速,可靠,并在編譯前發(fā)現(xiàn)錯(cuò)誤! 我認(rèn)為這是VSCode的最佳功能之一,就像有另一雙眼睛一樣。
減輕我的挫敗感
當(dāng)時(shí),每個(gè)插件的Sublime都很慢,并且缺少IntelliSense,VSCode很快,并且在發(fā)布之前一直保持增長,老實(shí)說,這么好的軟件是免費(fèi)的。
一切都按預(yù)期進(jìn)行,具有我能想到的所有功能,而那些不應(yīng)該成為核心的人是擴(kuò)展,說實(shí)話掌握它是值得的。
總之,一個(gè)描述我的VSCode代碼經(jīng)驗(yàn)的短語:我沒有任何抱怨。
> Banner from Xpgraph blog post
ReactJS
從他們的主頁:
一個(gè)用于構(gòu)建用戶界面的JavaScript庫
如前所述,我從AngularJS開始,這是前端包含完整電池的框架,但是遷移到React對(duì)我來說是不可避免的,這就是為什么:
不是框架
是的,不是框架,那是我最喜歡的東西之一,我通常編寫小型程序,不需要大量的框架,只需要一點(diǎn)幫助我就可以構(gòu)建小型UI。
擁抱函數(shù)式編程
最好的賣點(diǎn)是,React接受了函數(shù)式編程,與我對(duì)JavaScript的新認(rèn)識(shí)保持一致。
React做出了簡潔的努力,我對(duì)此表示贊賞。 React用最少的語法表達(dá)了復(fù)雜的概念,諸如useState和High Order Components之類的例子是使用正確的抽象要比使用一堆可能最終使用錯(cuò)誤的工具要好得多的例子。
一起+ TypeScript
我不使用Svelte或Vue的原因是我不喜歡模板,而我喜歡類型。 在模板文件中,您沒有TypeScript,也沒有JavaScript,但有模板腳本式的臨時(shí)標(biāo)記,可以幫助您處理各種類型的未鍵入內(nèi)容。
我真的很喜歡React的本質(zhì)。 意思是我使用css而不是CSS,而不是html + JS,而在TypeScript中使用TSX,所有CSS,HTML和JS,并且我喜歡它,所有內(nèi)容都具有IntelliSense,編譯錯(cuò)誤,類型,沒有上下文切換 。
如我所見,小型組件是CSS + HTML + JS的混合物,將它們?nèi)亢喜⒌絋ypeScript中對(duì)我有利。
更好的一面呢? 它的性能卓越,并且在每個(gè)新版本中都在不斷改進(jìn),將更多的JSS轉(zhuǎn)換為靜態(tài)CSS,對(duì)更多的TSX進(jìn)行了優(yōu)化等,因此您可以進(jìn)行慣用的編程,并且隨著時(shí)間的推移,編譯器可以改善輸出。
在我所服務(wù)的公司中,我們使用小型程序而不是低級(jí)的東西來編寫高級(jí)概念,我相信公司大部分時(shí)間都不會(huì)付錢給程序員來優(yōu)化任何東西,他們想要快速可用且可靠的軟件。
> Photo by Paxson Woelber on Unsplash
Ramda
現(xiàn)在讓我們變得奇怪,我不希望您從他們的主頁了解這一點(diǎn):
JavaScript程序員的實(shí)用功能庫。
我可以花幾個(gè)小時(shí)寫有關(guān)Ramda的文章,我將嘗試總結(jié)為什么在100%的項(xiàng)目中使用Ramda的最暢銷點(diǎn):
Lodash
如此多的人曾經(jīng)或曾經(jīng)將Lodash用作實(shí)用腰帶,但是Lodash對(duì)我來說是一個(gè)大問題,所有爭論都是落后的。 如果考慮可組合軟件,您很快就會(huì)意識(shí)到,如果要組合兩個(gè)Lodash函數(shù),則需要一個(gè)中間的"輔助"變量。 我寧愿不這樣。
另一方面,Ramda在設(shè)計(jì)時(shí)考慮了成分,在咖喱和煙斗的幫助下,精心打造了均勻的界面。
代碼可重用性
上面我一直抱怨重復(fù)代碼,大多數(shù)代碼都是小型實(shí)用程序函數(shù),如果我啟動(dòng)另一個(gè)項(xiàng)目后必須設(shè)法將所有文件夾都包含在其中,那么我不得不再次編寫它們,因此我一直在尋找一個(gè)重復(fù)的代碼。 好的實(shí)用程序庫。
現(xiàn)在,我?guī)缀鯖]有考慮過抽象函數(shù)以使其具有更高的可重用性,因?yàn)樗型ㄓ玫目芍赜煤瘮?shù)都在Ramda中,并且具有非常強(qiáng)大的功能優(yōu)先接口。
純功能,無副作用且不變
公用事業(yè)帶應(yīng)包含純粹的功能,這意味著這些功能必須:無副作用,并將數(shù)據(jù)視為不可變的。 這些東西與實(shí)用程序庫不一致,哎呀,甚至在JavaScript內(nèi)置Array函數(shù)中也不一致,不相信我嗎? 看這個(gè):
您是否可以估計(jì)發(fā)現(xiàn)naiveArray行為所需的時(shí)間,如果您依靠它在應(yīng)用sort之后保持不變的話? 好的,抱歉,我不想引起您的癲癇發(fā)作。
我在代碼的每一段中都非常珍視這些東西,因此Ramda將其內(nèi)置在每個(gè)函數(shù)中的事實(shí)真是令人驚訝。
轉(zhuǎn)換器
轉(zhuǎn)換器的實(shí)用描述:
轉(zhuǎn)換器消除了組合多個(gè)陣列功能的性能損失。
我認(rèn)為圖像勝于文字,轉(zhuǎn)換器難以理解:
> https://jsperf.com/native-vs-ramad-vs-lodash-vs-immutable
Ramda充滿了換能器功能,這意味著性能非常好,您可以堆疊多個(gè)filter,map和21個(gè)其他功能,它將僅迭代數(shù)組并應(yīng)用一次功能,而不是N次。
一件事失蹤
Ramda很棒,但是所有的好東西都是有代價(jià)的……如果您正在考慮使用TypeScript。
Ramda類型的類型,類型推論和類型解析的復(fù)雜性貫穿整個(gè)屋頂。 最重要的是,主要貢獻(xiàn)者根本對(duì)TypeScript不感興趣。
他們似乎是一群了不起的開發(fā)人員,他們?cè)诓恍枰猅ypeScript的情況下就馴服了JavaScript,并且對(duì)將此驚人的庫移植到TypeScript的興趣為零。
那么它如何與TypeScript一起使用呢? 值得慶幸的是,其他開發(fā)人員承擔(dān)了為庫提供類型的任務(wù),并且他們精通TypeScript類型系統(tǒng)(我很理解這些簽名),但是似乎在每個(gè)發(fā)行版中都可以更好地工作。
要提供準(zhǔn)確而可推斷的TypeScript類型,這是一個(gè)艱巨的挑戰(zhàn),因?yàn)樗鼈儗?duì)JavaScript高級(jí)類型功能的要求如此之高,但是它們卻無法實(shí)現(xiàn),現(xiàn)在大多數(shù)功能可以在TypeScript中無縫使用,但是 最高級(jí)的需要一些幫助來確定類型的結(jié)果。
盡管如此,Ramda仍然是我樂于使用的最精良的實(shí)用程序庫之一,在我馴服JavaScript的過程中,它讓我非常感動(dòng)。 謝謝,拉姆達(dá)
FP-TS
只要我們留在JavaScript領(lǐng)域,Ramda就是一個(gè)了不起的解決方案,但是當(dāng)我完全采用TypeScript時(shí),它變得……笨拙地使用了,類型推斷并不是那么好,所以我搜索了其他考慮到TypeScript的解決方案,或者 更好的是用TypeScript編寫的。
幸運(yùn)的是,我從他們的主頁中找到了圖書館奇跡fp-ts:
TypeScript中的類型化函數(shù)式編程
fp-ts為開發(fā)人員提供了流行的模式以及來自TypeScript中類型化功能語言的可靠抽象。
老實(shí)說,fp-ts是一個(gè)杰作,它為TypeScript帶來了很多好處,并且以一種不引人注目的方式,它的類型也是完全慣用的。
為什么我在100%的項(xiàng)目中使用fp-ts?
管道
由于類型分析的從左到右的性質(zhì),我故意避免談?wù)揜amda的管道,因?yàn)閒p-ts版本對(duì)于TypeScript和IntelliSense更是慣用的。
這是沒有管道的代碼:
在main中,我需要使用中介變量來分配中介結(jié)果,在main2中,要從右到左讀取執(zhí)行順序是很尷尬的。
這是Ramda管道的代碼:
使用管道,我們不需要中間變量,不需要所有數(shù)據(jù)流,但是,在大多數(shù)情況下,TypeScript在使用Ramda管道時(shí)會(huì)產(chǎn)生錯(cuò)誤,因?yàn)檩斎胫滴挥谧詈螅虼藷o法推斷出第一個(gè)函數(shù)的輸入是什么, 依此類推,因?yàn)門ypeScript從左到右進(jìn)行推斷,并且Ramda的管道可以正常工作,所以推斷應(yīng)該同時(shí)從左到右和從右至左進(jìn)行,因此Ramda的管道類似于類型推斷系統(tǒng)中的一個(gè)共同特征。 功能語言,例如Haskell,OCalm和F#,但不是TypeScript中的語言,盡管JavaScript根本沒有問題。
現(xiàn)在看一下fp-ts版本的管道:
區(qū)別在于fp-ts將管道的輸入放在首位,從而使TypeScript推論變得愉快。 在JavaScript領(lǐng)域,Ramdas的方法是100%有效的慣用代碼,但是TypeScript缺少從右到左的推斷使其"無效"或通常很難使用,因此我通常傾向于使用fp-ts版本的管道,而不是 拉姆達(dá)的。
Option,Ether,TasksEither和其他FP數(shù)據(jù)結(jié)構(gòu)
我很自豪地宣布,我再也很少遇到未定義和null錯(cuò)誤,因?yàn)樽詈螅矣辛薕ption的慣用且完全受支持的實(shí)現(xiàn)。
Option基本上是表示可能存在或不存在值的數(shù)據(jù)的包裝器。
另一方面,允許輕松地分叉代碼,事情可以向左或向右移動(dòng)。
讓我舉一個(gè)例子:
哦,這真是一個(gè)不錯(cuò)的代碼。 這么小的代碼沒有錯(cuò)。
除了,一切。 但是我們并不是那么愚蠢,我們可以改善,拋出一些if并嘗試…捕獲表達(dá)式,然后就一切就緒了。
現(xiàn)在可以了。 在該示例中,我向您展示JavaScript和TypeScript都無法指導(dǎo)您檢查這種情況,也許帶有–strictNullChecks的TypeScript會(huì)有所幫助,但是函數(shù)返回類型不能表示錯(cuò)誤,但這不是全部,分支都被弄亂了 向上,我返回了早期錯(cuò)誤和晚期錯(cuò)誤,并且在中間成功了嗎? 現(xiàn)在來看這個(gè):
如您在本例中看到的,Option和Either都迫使我們以顯式方式處理分支,沒有"遺漏分支",我們可以用Either的左分支表示Errors,而我們只在最后返回。
如果預(yù)計(jì)會(huì)出現(xiàn)"錯(cuò)誤",為什么要使用try … catch? 這是預(yù)期的行為,try … catch習(xí)慣于"出乎意料的錯(cuò)誤",但是對(duì)于預(yù)期的邏輯分支,無論是完美的抽象,事情都可以向左(錯(cuò)誤)或向右(成功)。
這些數(shù)據(jù)結(jié)構(gòu)可幫助我們構(gòu)造更高級(jí)的數(shù)據(jù)流模式(如Rail Way編程),如果您不知道我在說什么,請(qǐng)查看此頁面:https:
//fsharpforfunandprofit.com/rop/。
最后但并非最不重要的一點(diǎn)是,我將提到TaskEither,任務(wù)基本上是Promise的包裝器,但具有更為單調(diào)的界面,這個(gè)奇怪的詞是什么意思? 這意味著它更適合標(biāo)準(zhǔn)接口,而不是像Promise這樣的古怪實(shí)例方法,可以使用完善的map,chain,ap,fold等。
好的,如果您還不熟悉函數(shù)式編程,那么在代碼庫中當(dāng)然不能很好地建立ap和fold,但是一旦找到,您會(huì)注意到函數(shù)的統(tǒng)一性,無論封裝數(shù)據(jù)如何,都意味著相同 結(jié)構(gòu),無論您要映射的是數(shù)組,對(duì)象,選項(xiàng),Either還是TaskEither,映射都意味著相同,它對(duì)每個(gè)數(shù)據(jù)結(jié)構(gòu)都有詳細(xì)說明,但是map在所有情況下都是map, 統(tǒng)一,無需學(xué)習(xí)(在函數(shù)式編程中)經(jīng)過充分研究的轉(zhuǎn)換的另一種重新實(shí)現(xiàn)。
這些只是使您的代碼真正表達(dá)意圖,更簡潔并最終更可靠的功能數(shù)據(jù)結(jié)構(gòu)中的3個(gè)。
X狀態(tài)
讓我介紹XState作為應(yīng)該已經(jīng)取代Redux的庫。 從他們的主頁:
現(xiàn)代網(wǎng)絡(luò)的JavaScript和TypeScript有限狀態(tài)機(jī)和狀態(tài)圖。
很長時(shí)間以來,我的Redux商店都缺少一些東西,我試圖制作一些小的中間件來幫助我馴服Redux,但是感覺……不完整。 直到我中獎(jiǎng)并找到XState。
為什么我在100%的React項(xiàng)目中使用XState?
有限狀態(tài)機(jī)
我的問題是Redux只是問題的一半,而沒有注意到我在每個(gè)React組件中都制作了小型狀態(tài)機(jī),并在擴(kuò)展?fàn)顟B(tài)(或無限狀態(tài))中使用Redux,一旦我發(fā)現(xiàn)XState,我所有的設(shè)計(jì)問題都遇到了一個(gè)有價(jià)值的競(jìng)爭者。
應(yīng)該顯示一個(gè)按鈕嗎? 已啟用? 顯示文字A或B? 所有這些"域"規(guī)范都不超過幾個(gè)有限的事先指定的狀態(tài); 如果您明確地編寫了這樣的狀態(tài),則讀取和升級(jí)組件將成為一件樂事。
使用AngularJS和模板,我的狀態(tài)由一堆無法讀取的交織在一起的變量組成,使用React和Redux,所有數(shù)據(jù)都放在一個(gè)地方,但是狀態(tài)沒有以任何方式表示,是對(duì)數(shù)據(jù)的解釋,但是 使用XState我的狀態(tài)實(shí)際上是明確的。 看看這臺(tái)機(jī)器:
如果您是像我這樣的圖形人物,則可以嘗試使用XState可視化工具:
我需要向您解釋這臺(tái)機(jī)器的行為嗎? 不,我不知道 在那里,肉眼看不到,沒有奇怪的曼波大貓。
我們推出了三本新出版物! 通過關(guān)注它們來表達(dá)對(duì)我們新出版物的熱愛:普通英語的AI,普通英語的UX,普通英語的Python –謝謝并繼續(xù)學(xué)習(xí)!
我們也一直對(duì)幫助推廣高質(zhì)量的內(nèi)容感興趣。 如果您有要提交給我們?nèi)魏纬霭嫖锏奈恼拢?qǐng)使用您的中等用戶名給我們發(fā)送電子郵件至submittings@plainenglish.io,我們將使您成為作家。 另外,請(qǐng)告訴我們您要添加到哪個(gè)出版物。
(本文翻譯自Edgar Rodríguez的文章《The 6 tools that changed JavaScript for me》,參考:
https://medium.com/javascript-in-plain-english/the-6tools-that-changed-javascript-for-me-3ee1faf40585)