1. 程式人生 > >在 2016 年學 JavaScript 是一種什麽樣的體驗?

在 2016 年學 JavaScript 是一種什麽樣的體驗?

form jad 說過 變更 排序。 思路 聽說 oda 部分

感謝原作者分享,原文地址:https://zhuanlan.zhihu.com/p/22782487

嘿,我最近接到一個 Web 項目,不過老實說,我這兩年沒怎麽接觸 Web 編程,聽說 Web 技術已經發生了一些變化。聽說你是這裏對新技術最了解的 Web 開發工程師?

準確地說,我是一名「前端工程師」。不過你算是找對人了。我對今年的技術別提多熟了,前端可視化、音樂播放器、能踢足球的無人機,你盡管問吧。我剛去 JS 大會和 React 大會逛了一圈,沒有什麽新技術是我不知道的。

厲害。是這樣的,我要開發一個網頁,用來展示用戶的最新動態。我想我應該通過後端接口獲取數據,然後用一個 table 來展示數據,用戶可以對數據進行排序。如果服務器上的數據變化了,我還需要更新這個 table。我的思路是用 jQuery 來做。

可別用 jQuery!現在哪還有人用 jQuery。現在是 2016 年了,你絕對應該用 React。

哦,好吧,React 是什麽?

React 是一個非常厲害的庫,Facebook 的牛人寫的。它能讓頁面更可控,性能極高,而且使用起來很簡單。

聽起來確實不錯。我能用 React 展示服務器傳來的數據嗎?

當然可以,你只需要添加兩個依賴,一個是 React,一個是 React DOM

額,等下,為什麽是兩個庫?

React 是我說的庫,React DOM 是用來操作 DOM 的。因為這些 DOM 是用 JSX 寫的,所以需要一個專門的庫來操作。

JSX?JSX 是什麽?

JSX 是對 JS 的擴展,它看起來跟 XML 差不多,可以用來寫 HTML,你可以認為 JSX 是一種更優雅的 HTML 寫法。

為什麽不用 HTML 了……?

現在可是 2016 年啊,沒有直接寫 HTML 的。

對哦。好吧,加了這兩個依賴,是不是就可以開始用 React 了?

不行哦。你需要添加 Babel,然後才能用 React。

Babel 是另一個庫?

嗯,Babel 是一個轉譯工具,Babel 能把你寫的 JS 轉譯成任意版本的 JS。你不一定非要用 Babel,但是如果你不用的話,你就只能寫 ES5 的語法了。你知道的,現在是 2016 年,你怎麽能不使用 ES2016+ 的語法呢?ES2016+ 多麽酷啊。

ES5 是啥?ES2016+ 又是啥?我有點暈。

ES5 就是 ECMAScript 5。大部分人都會使用 ES5,因為大部分瀏覽器都支持 ES5。

ECMAScript 是啥……

你曉得的,JS是1995年誕生的,而JS的標準是1999制定出來的。那時候 JavaScript 還叫做 Livescript,只能運行在網景的瀏覽器裏。那時真是混亂的年代,現在好了,我們有了 JS 的 7 個版本的規範。

7 個版本?那 ES5 和 ES2016+ 是?

分別是第 5 個版本和第 7 個版本。

誒,那第六個版本呢?

你說的是 ES6。每個版本都是上一個版本的超集,所以你直接使用最新的 ES2016+ 就好了。

對哦。為什麽不用 ES6 呢?

好吧,你可以用 ES6,但是你就用不到 async 和 await 這麽酷的語法了。用 ES2016+ 比較好。用 ES6 的話你就只能用 generator 來控制異步任務流了。

不知道你在說什麽……你說了太多我聽不懂的名詞了。我只是想從服務器取點數據,我以前用 jQuery 挺好的,從 CDN 引入 jQuery,我就能用 AJAX 獲取數據了,現在不能這樣做嗎?

大哥,都 2016 年了,沒人用 jQuery 好嗎。所有人都知道用 jQuery 只會造出「意大利面條」一樣的代碼(不可維護)

好吧,所以我現在要加載三個庫才能獲取並展示數據。

對的,其實你可以用「模塊管理器」把這三個庫「打包」成一個文件。

哦,什麽是模塊管理器……

不同平臺的模塊管理器不同啦。前端的模塊管理器一般指管理 AMD 或者 CommonJS 模塊的東西。

好……吧,什麽是 AMD 和 CommonJS?

是兩個定義。我們有很多方式來描述 JS 中多個庫或類的交互方式,比如 exports 和 requires。你可以按照 AMD 或者 CommonJS 的 API 來書寫 JS,然後用 Browserify 將它們打包。

聽起來很有道理。不過,什麽是 Browserify?

是一個工具,用來將 CommonJS 形式的 JS 文件打包起來,放到瀏覽器裏運行。用 npm 倉庫的人發明了 CommonJS。

npm 倉庫是什麽……

是一個公開的倉庫,用於放置可依賴的模塊。

就像一個 CDN 麽?

不太一樣。它更像是一個數據庫,每個人都能在上面發布代碼,也能下載上面的代碼。你可以在開發的時候將這些代碼下載到本地來使用,必要的時候也能上傳到 CDN。

聽起來像是 Bower!

是的,不過現在是 2016 年了,沒有人用 Bower 了……

好吧,我知道了,所以我應該用 npm 來安裝依賴。

對的。我舉個例子吧,如果你要使用 React,你直接用 npm 安裝 React,然後在代碼裏導入 React 就可以了。大部分 JS 庫都能這麽安裝。

嗯,Angular 也可以。

Angular 是 2015 年的事情了。不過今年 Angular 還沒死,還有 VueJS 和 RxJS 等等,你想學一學麽?

還是用 React 吧。我剛才已經學了夠多東西了。所以我用 npm 安裝 React 然後用 Browerify 來打包就好了?

是的。

這麽做看起來有點過於復雜啊。

確實。這就是為什麽你應該使用 Grunt、Gulp 或者 Broccoli 這樣的任務管理工具,它們能自動運行 Browserify。不對,你現在可以用 Mimosa。

你在說什麽……

任務管理工具。不過我們現在已經不用了。去年我們還在用,後來改成了 Makefiles,但是現在我們用的都是 Webpack。

我以為只有 C/C++ 項目才會用 Makefiles。

是的,不過顯然我們做 Web 開發的,喜歡先把事情搞復雜,然後回歸到最樸素的狀態。每年我們都是這麽搞的。你就看著吧,過不了兩年,我們就可以在網頁上寫匯編了。

唉,你剛才說的 Webpack 是什麽?

另一種模塊管理工具,同時也是一個任務管理工具。你可以認為它是 Browserify 的加強版。

哦,好吧,為什麽 Webpack 是加強版?

額,可能並沒有加強吧。Webpack 告訴你應該如何管理你的依賴,Webpack 允許你使用不同的模塊管理器,不只是 CommonJS,甚至支持 ES6 模塊。

這都是哪跟哪啊,我都被繞暈了。

大家都被繞暈了,不過等 SystemJS 出來了就好了。

天吶,又一個 JS 庫,這是什麽鬼?

呵呵,不像 Browserify 和 Webpack 1.x,SystemJS 是一個動態的模塊加載器。

等下,剛才不是說應該把所有依賴打包成一個文件嗎?

話是這麽說,但是等 HTTP/2 普及之後,不打包反而更好。

那為什麽我們不直接在頁面裏添加 React 的三個依賴文件呢?

不行。你可以從 CDN 加載這些文件,但是你還是要在本地用 Babel 轉譯。

唉,這麽鹺?

是的,你不能在生產環境上運行 babel,你應該在發布到生產環境之前,運行一系列的任務,包括壓縮、混淆、內聯化CSS、延遲加載script……

我懂了我懂了。既然我不能直接用 CDN,那麽我應該怎麽做?

我會考慮用 Webpack + SystemJS + Babel 來轉譯 Typescript。

Typescript?我們不是在說 JavaScript 嗎?!

Typescript 也是 JavaScript 呀,它比 JS 更好用,是 JS 的超集,它是基於 ES6 的,就是我們剛才談論的 ES6,你還記得吧。

ES2016+ 已經是 ES6 的超集了,怎麽又冒出來一個 Typescript?

是這樣的,Typescript 能讓我們寫出「強類型」的 JS,從而減少運行時的錯誤。2016年,我們應該讓 JS 支持強類型了。

顯然 Typescript 可以做到。

Flow 也可以做到,區別是 Typescript 需要編譯,而 Flow 只是檢查語法。

唉,Flow 是?

是一個靜態類型檢查器,就是 Facebook 的人寫的。使用 OCaml 寫的,函數式編程很叼的。

OCaml?函數式編程?

如今大牛都用這些東西,都2016年了,你懂的,函數式編程、高階函數、柯裏化、純函數這些概念。

不知道你在說什麽。

一開始大家都不知道。這麽說吧,你只需要知道函數式編程比面向對象編程厲害,2016 年我們就指著函數式編程了。

等下,我大學裏學過面向對象編程,當時我覺得它還不錯。

Java 在被 Oracle 買下來之前也挺不錯啊。我的意思是,面向對象以前是不錯,現在依然有人用它,但是現在所有人都發覺狀態變換是很難維護的,所以大家都開始用「不可變對象」和函數式編程了。Haskell 的人已經用這套東西用了很久了,不過幸運的是 Web 開發領域裏有 Ramda 這樣的庫,讓我們用 JS 就可以進行函數式編程了。

你剛剛是不是又拋出了幾個名詞?Ramnda 又是什麽?

不是 Ramnda,是 Ramda,跟 Lambda 表達式有點像。是 David Chambers 寫的庫。

誰?

David Chambers,大神一個。blablabla

我不得不打斷你一下了。這些東西看起來都不錯,但是我覺得它們都太復雜,而且沒必要。我只是想獲取數據然後展示,我很確定這種情況下我不需要掌握這些知識。

回到 React 吧,用 React 我怎麽從服務器獲取數據?

額,React 沒有提供這個功能,你只能用 React 展示數據。

服了啊。那我怎麽獲取數據?

你用 Fetch API 就可以了。

啥玩意?這個 API 的名字很爛啊。

我也覺得是啊。Fetch API 是瀏覽器提供的異步請求接口。

哦,那不就是 AJAX。

AJAX 只是使用 XMLHttpRequest 對象,但是 Fetch API 可以讓你用 Promise 風格來發起異步請求,幫你擺脫「回調地獄」。

回調地獄?

是的,每次你發起一個異步請求,就得等待它響應。這時你就得在函數裏使用一個函數,這種嵌套調用就是回調地獄。

好吧。Promise 解決了這個問題麽?

是的。用 Promise 來管理回調,你就可以寫出更易讀的代碼,更容易測試的代碼。甚至可以同時發起多個請求,然後等待它們全部返回。

Fetch 也能做到嗎?

是的。但前提是你的用戶使用了新版的瀏覽器,不然的話你就需要加一個 Fetch 的 「polyfill」,或者使用 Request、Bluebird 或者 Axios 這些庫。

天吶我到底需要多少個庫?

這是 JS,同一件事情有上千個庫在做。我們了解庫,而且我們有最好的庫,我們有海量的庫,要什麽有什麽。

你剛才說的幾個庫都是幹什麽的?

這幾個庫操作 XMLHttpRequest 然後返回 Promise 對象。

好像 jQuery 的 ajax 方法做的是同樣的事吧……

從 2016 年起我們就不用 jQuery 了。用 Fetch,大不了加個 Polyfill,要不然用 Bluebird、Request 或者 Axios 都行。然後用 await 和 async 管理 Promise,這樣才能控制好異步任務。

這是你第三次說 await 了,那是什麽東西?

await 能讓你攔住一個異步調用,讓你更好地控制異步返回的數據,大大增強了代碼的可讀性。await 非常好用,你只需要在 Babel 裏添加 stage–3 配置,或者添加 syntax-async-functions 和 transform-async-to-generator 插件就可以了。

聽起來像是瘋了。

沒瘋。為了使用 await,把 Typescript 編譯之後再用 Babel 轉譯一道的人才是瘋了。

啥玩意?Typescript 不支持 await?

下個版本就支持了。

我已經無話可說了。

你看其實很簡單。用 Typescript 寫代碼,用 Fetch 發起異步請求,所有代碼編譯成 ES6,然後用上 Babel 的 stage–3 配置項,把 ES6 轉譯成 ES5。所有代碼用 SystemJS 加載。如果你用不了 Fetch,就加個 polyfill,或者用 Bluebird、Request 或者 Axios,這樣你就可以用 await 來處理 Promise 了。

看來我們倆對於「簡單」的理解是不同的。好吧,有了這些,我終於可以獲取數據然後用 React 展示數據了,對吧?

你的網頁需要處理狀態變更嗎?

唔,不用吧。我只是想展示數據。

那就好,不然我就得跟你解釋 Flux,以及 Flux 的一些實現,比如 Flummox、Alt、Fluxible。不過說真的你應該用 Redux。

你說的這些我就當耳旁風了。再說一次,我只想展示數據。

這樣啊,如果你只是想展示數據,其實你不需要 React。你只需要一個模板引擎。

你逗我呢?

我只是告訴你你可以用什麽技術。

別說了,真的。

我想說,即使只是用一個模板引擎,我還是會用 Typescript + SystemJS + Babel 的。

我只是想在頁面上展示數據,你就告訴我用哪個模板引擎就好了。

有很多,你用過哪一個?

額,太久沒用了,不記得了。

jTemplates、jQote 還是 PURE?

額,不記得,還有別的麽?

Transparency? JSRender? MarkupJS? KnockoutJS? 這一個支持雙向綁定。

還有嗎?

PlatesJS? jQuery-tmpl? Handlebars? 還有些人在用。

有點像。有哪些跟最後一個比較像的?

Mustache, underscore? 我記得連 Lodash 都有一個模板引擎,不過這是 2014 年的事情了。

額,也許是再新一點的庫?

Jade? DustJS?

沒用過

DotJS? EJS?

沒用過。

Nunjucks? ECT?

沒用過。記不起來了,要是你的話,你用哪個?

我應該會用 ES6 原生的模板字符串

我猜猜,只有 ES6 支持。

對的。

需要用 Babel

對的。

需要用 npm 安裝

對的。

需要用 Browserify 或者 Webpack,或者 SystemJS

對的。

如果沒用 Webpack 的話,我還需要一個任務管理工具。

對的。

但是由於我要用函數式編程和強類型語言,所以我首先要用上 Typescript 或者 Flow。

對的。

如果我要用 await,那我就必須用 Babel 轉譯。

對的。

然後我就能用上 Fetch、Promise 和各種炫酷的東西。

嗯,別忘了加上 Fetch 的 Polyfill,因為 Safari 不支持 Fetch。

你猜怎麽著,我們就聊到這吧。我不做了,我不做 Web 了,我也不想再碰 JS 了。

沒事,過不了幾年,我們都會用 Elm 或者 WebAssembly 了。

我要回後端去了,我受不這些變動、版本更新、編譯和轉譯了,JS 社區如果覺得有人能跟上它的腳步,那這個社區就是瘋了。

我理解你。我建議你去 Python 社區。

為什麽?

聽說過 Python 3 嗎?

完。

譯者註:最後一句「聽說過 Python 3 嗎?」是諷刺 Python 3 發布已經 8 年了,Python 社區卻依然在使用 Python 2.7。而 JS 社區正好相反,把還沒有實現的語言特性都用到生成環境中了!

譯者:方應杭

平時想跟我交流前端的話,可以加群,群號在我的個人頁面第一行,加群暗號:2016JS。

非誠勿擾。

在 2016 年學 JavaScript 是一種什麽樣的體驗?