[譯] 咱們能從 Redux 源碼中學到什麼?

咱們能從 Redux 源碼中學到什麼?

我老是聽人說,想拓展開發者自身視野就去讀源碼吧。html

因此我決定找一個高質量的 JavaScript 庫來深刻學習。前端

我選擇了 Redux,由於它的代碼比較少。node

這篇文章不是 Redux 教程,而是閱讀源碼後的收穫。若是你對學習 Redux 感興趣,強烈推薦你去看 Redux 教程,這個系列文章是 Redux 的做者 Dan Abramov 寫的。react

從源碼中學習

一些新來的開發者常常問我,怎樣纔是最好的學習方式?我每每會告訴他們在項目中學習。android

當你構建一個項目來實踐你的想法時,因爲你對它的熱愛,會讓你度過難熬的 debug 階段,即便遇到困難也不會放棄。這是一個很是神奇的現象。ios

可是一我的閉門造車也是有問題的。你不會注意到你開發過程當中的壞習慣,你也學不到任何最優的解決方案。你可能都不知道又出了哪些新的框架和技術。在獨自寫項目的過程當中,你很快會發現你的技能達到瓶頸。git

只要有可能,我建議你找些小夥伴和你一塊兒開發。github

試想一下,坐在你旁邊的小夥伴(若是你夠幸運,他剛好是個大神),你能夠觀察他思考問題的過程。你能夠看他是如何敲代碼的。你能夠看他是如何解決算法問題的。你能夠學到新的開發工具和快捷鍵。你會學到許多你一我的開發時學不到的東西。算法

斯特拉迪瓦里小提琴。npm

我用斯特拉迪瓦里的小提琴舉個例子。斯特拉迪瓦里小提琴以出色的音質聞名世界,在業界能夠說是一枝獨秀。許多人嘗試用各類方法去解釋爲何它這麼牛逼,從古老教堂搶救出來的木材到特殊的木材的防腐劑。許多人想要複製一把斯特拉迪瓦里小提琴,結果都失敗了,由於他們不知道安東尼·斯特拉迪瓦里究竟是怎麼作的。

設想一下,若是你和安東尼·斯特拉迪瓦里在一個房間裏工做,那麼全部的獨門祕籍你均可以學到。

這下你知道該如何與你的開發小夥伴相處了吧。你只須要安靜的坐他旁邊,看着他寫出一行行斯特拉迪瓦里式的代碼。

對於與多人來講,協同編程是一個很好的機會,能夠經過別人的代碼學到不少東西。

閱讀高質量的代碼就像讀一本精彩的小說同樣,比起直接和做者交流,你可能理解起來比較困難。可是你能夠經過看註釋和代碼,獲取到有價值的信息。

對於那些認爲看源碼沒什麼用的的同窗,你能夠去看一個故事,一個叫比爾·蓋茨的高中生,爲了瞭解某個公司的機密,他甚至去翻人家的垃圾桶找源碼。

若是你也能夠像比爾·蓋茨那樣不厭其煩的看源碼,那還在等什麼?找一個 github 倉庫,看源碼吧!

咦,源碼呢?

閱讀源碼的同時,你也能夠去看官方文檔,官方文檔的結構就像做者寫的代碼同樣,寫得好的官方文檔就讓你彷彿坐在做者旁邊同樣。你也能夠在上面看到別人遇到的問題。官方文檔中的超連接提供了豐富的擴展閱讀的資源。在評論區你還能夠和大神一塊兒交流。

平時我也會在 YouTube 看別人寫代碼,我推薦你們去看SuperCharged 直播寫代碼系列,來自 Google Chrome 開發者的 Youtube 頻道。看兩個 Google 工程師直播寫一個項目,看他們是如何處理性能問題的,和你們同樣,他們也會被本身拼寫錯誤致使的 bug 卡住。

讀 Readux 源碼的收穫

ESLint

Linting 用於檢查代碼,發現潛在的錯誤。它幫助咱們保持代碼風格的一致性和整潔。你能夠本身定製規則,也能夠用預設的規則(好比 Airbnb 提供的規則)。

Linting 在團隊開發中特別有用。它讓全部代碼看起來像一我的寫的。它能夠強迫開發人員按照公司的代碼風格來寫代碼(同事不用在閱讀代碼上花太多時間)。

Linters 不只僅是爲了美觀,它會讓你的代碼更符合語言特性。好比它會告訴你何時使用 「const」 關鍵字來處理那些沒有被從新賦值的變量。

若是你使用了 React 插件,它會警告你關於組件能夠被重構成無狀態的函數式組件。也是可讓你學習 ES6 語法,告訴你的某段代碼能夠用語法新特性來寫。

在你的項目中輕鬆使用 ESlint:

  1. 安裝 ESlint。
$ npm install --save-dev eslint
複製代碼
  1. 配置 ESlint。
./node_modules/.bin/eslint --init
複製代碼
  1. 在你的 package.json 文件中設置 npm 腳原本運行你的 Linter(可選)。
"scripts": {
  "lint": "./node_modules/.bin/eslint"
}
複製代碼
  1. 運行 Linter.
$ npm run lint
複製代碼

查看它們的官方文檔,瞭解更多。

許多編輯器也有插件來檢查你的代碼。

有些時候 Linter 會對一些正確的代碼報錯,好比 console.log。你能夠告訴 Linter 忽略這行代碼,不對其進行檢查。

在 ESlint 中忽略檢查,你能夠這樣寫代碼註釋:

// 忽略一行
 console.log(‘Hello World’); // eslint-disable-line no-console
// 忽略多行
 /* eslint-disable no-console */
 console.log(‘Hello World’);
 console.log(‘Goodbye World’);
 /* eslint-enable no-console */
複製代碼

檢查代碼是否被壓縮了

在源碼中我發現一個 「isCrushed()」 的空函數,很奇怪。

後來我發現它的目的是爲了檢查代碼是否被壓縮了。在代碼壓縮過程當中,函數名字和變量會被縮寫。當你在開發的時候若是使用了壓縮後的代碼,若是一個條語句被檢測到仍然有 「isCrushed()」 存在,就會有警告提示。

不要懼怕報錯

在學習 Redux 源碼以前我不多在代碼中拋異常。JavaScript 是一個弱類型,因此咱們不知道函數中傳入參數的類型。因此咱們必需要像強類型語言那樣對於錯誤要拋出異常。

使用 try…catch…finally 語句來拋出異常。這樣作能夠方便你 debug,以及理清代碼邏輯。

在控制檯中產生的錯誤,能夠很方便堆棧跟蹤。

頗有用的棧跟蹤。

作異常信息處理讓你的代碼邏輯清晰。好比,若是有一個 "add()" 函數,只容許傳入數字,若是傳入的不是數字就要拋出異常。

function add(a, b) {
    if(typeof a !== ‘number’ || typeof b !== ‘number’) {
	throw new Error(‘Invalid arguments passed. Expected numbers’);
    }
    return a + b;
}
var sum = add(‘foo’, 2); 
// 拋出異常後會終止代碼執行
複製代碼

組合函數

源碼中有一個 「compose()」 函數,根據已有的函數構建出新的函數:

function compose(…funcs) {
   if (funcs.length === 0) {
     return arg => arg
   }
   if (funcs.length === 1) {
     return funcs[0]
   }
   const last = funcs[funcs.length — 1]
   const rest = funcs.slice(0, -1)
   return (…args) => rest.reduceRight((composed, f) => f(composed),    last(…args))
 }
複製代碼

若是我有兩個已知的 square 函數和另外一個 double 函數,我能夠把它們組成一個新函數。

function square(num) {
   return num * num;
 }
function double(num) {
   return num * 2;
}
function squareThenDouble(num) {
   return compose(double, square)(num);
}
console.log(squareThenDouble(7)); // 98
複製代碼

若是我沒看過 Redux 的源碼,我都不知道還有這種犀利的操做。

原生方法

當我在看 「compose」 函數的時候,我發現了一個原生數組方法 「reduceRight()」,我以前都沒聽到過。這讓我想知道還有多少我沒聽過的原生方法。

咱們來看一個代碼片斷,一個使用了原生數組方法 「filter()」,一個沒有,經過對比看原生方法存在的價值。

function custom(array) {
   let newArray = [];
   for(var i = 0; i < array.length; i++) {
     if(array[i]) {
       newArray.push(array[i]);
     }
   }
   return newArray;
 }
 function native(array) {
   return array.filter((current) => current);
 }
 const myArray = [false, true, true, false, false];
 console.log(custom(myArray));
 console.log(native(myArray));
複製代碼

你能夠看到使用 「filter()」 會讓你的代碼變得簡潔。更重要的是,避免了重複造輪子。「filter()」 會被使用上百萬次,比起你本身造輪子,能夠避免不少 bug。

當你想造輪子的時候,先看看你的問題是否已經被原生方法解決了。你會驚喜的發現有很是多的實用方法在你用的編程語言中。(好比,能夠看看 Ruby 的數組的從新排列的方法

描述性的函數名

在源碼中,我看到了許多有很長名字的函數。

  1. getUndefinedStateErrorMessage
  2. getUnexpectedStateShapeWarningMessage
  3. assertReducerSanity

雖然這函數名讀起來會讓你的舌頭打結,但你能夠清楚的知道這個函數是作什麼的。

在你的代碼中使用描述性的函數名,讓你更多的是讀代碼而不是寫代碼,別人也能夠很輕鬆的閱讀你的代碼。

用較長的描述性函數名帶來的好處遠超過敲擊鍵盤所帶來的快感。現代的文本編輯器都有自動補全功能,它能夠幫助你輸入,因此沒有理由再使用相似 「x」 或者 「y」 的變量名。

console.error vs. console.log

不要老是使用 console.log,若是你要拋出異常,請使用 console.error,你能夠在 console 中看到紅色的打印內容和棧的跟蹤。

console.error()

查看 console 文檔,看看其餘的方法。好比計算運行時間的計時器(console.time()),用表格方式打印信息(console.table()),等等。


不要懼怕去讀源代碼。你確定會學到一些東西,甚至能夠爲它貢獻代碼。

在評論中分享你在閱讀源碼中的收穫吧!


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索