如何編寫高質量的函數 -- 命名/註釋/魯棒篇

此篇我將會從函數的命名、註釋和魯棒性方面,闡述如何編寫高質量的函數。前端

PS:這一篇相對上一篇文章要簡單好懂多了。node

引言

寫第二篇以前,先說個事情。針對前面我寫的 如何編寫高質量的函數 -- 敲山震虎篇 文章的評論區,小夥伴提出的一些問題,我也所有都看了,特此寫了答疑篇。react

答疑篇放在了 issues 上,點擊下面連接便可 TP :git

如何編寫高質量的函數 -- 敲山震虎的答疑篇github

對個人回答有什麼疑問的話,能夠 issues 討論,這篇文章就不放在掘金了。web

PS: 提一下一些公衆號(掘金,奇舞週刊等)轉載的狀況,因爲文章一開始有錯誤,而後公衆號又沒有同步,而後我又不能幫大家改,因而點開公衆號文章,看着那些還在的錯誤,卻無能爲力的心情,內心默默 ob : 感謝地主們的轉載,那就這樣吧😂。面試

好,胡謅很少說,直接開始吧。express

函數命名

從文章開頭的圖片能夠知道,命名和緩存是計算機科學中的兩大難題。npm

而今天要說的是函數命名,雖然函數命名涉及到的範圍較窄,但思想都是同樣的,徹底 能夠借鑑到其餘的形式中。編程

我閱讀過代碼大全的變量一章,也針對性的閱讀過一些源碼,好比 lodash , ramda 這些函數工具庫。如今根據我我的的一些感悟,總結了一些我我的認爲能幫助你完全解決命名這個事情的 best practice

PS: 雖然變量命名這個沒有所謂 best practice ,可是對於前端的函數命名來講,我我的認爲是能夠有一套完善的 best pratice 的, 聽我娓娓道來。

目前前端的函數命名存在什麼問題

存在什麼問題呢?要我說啊,那些業界標準,好比駝峯,首字母大寫的類和構造函數,下劃線,$ 等都不是瓶頸。真正的瓶頸是一些你察覺不到的,或者察覺到可是無能無力的細節。好比:

  • 中英語言的差別性
  • 不懂得從多維度去提高命名的準確性
  • 不會使用輔助工具

下面進行簡明扼要的分析。

PS: 關於駝峯等耳熟能詳的業界標準我就再也不提了。

漢語和英語的差別性

爲何一開始要說這個呢,由於我認爲這是目前命名中,存在的最大的問題。英語水平好的哥們沒多少,不少人不能掌握英語命名的那一套語法規則,說白了就是你英語水平達不到能像外國人那樣能寫出符合英語 style 的名字。

爲何不能用漢語方式命名呢?

理由就三個:

  • 用拼音的本質問題:漢語拼音存在多義性,想一想就瑟瑟發抖。
  • 用漢字的問題:雖然輔助工具已經很完善了,可是無法普及,無法和國際接軌,說白了就一句話,過小衆了,外國人沒有會的,不跟你玩。
  • 鄙視鏈已經造成(emmmm)。

用英語時遇到的困難

最大的困難就是 不會

我舉個例子,都知道 react 的生命週期吧,以下:

  • componentDidMount

  • componentWillReceiveProps

  • shouldComponentUpdate

不少人都會有疑問,爲何用 did ,爲何用 will 。行吧,記住就完事了,而後過了一段時間,面試的被問到了,而後內心 ob:componentMounted 仍是啥來...

多麼鮮活的例子,嗯,繼續往下讀吧,後面有驚(極)爲(爲)天(驚)人(悚)的答案。

如何讓命名有英語 style

黑人臉,怎麼讓啊?

老哥,多翻翻高中或者初中的英語語法知識吧。好比我舉個最簡單的例子,你就知道了。

componentDidMountreact 等生命週期的鉤子,可是爲何要這樣命名?

componentWillReceiveProps 爲何要這樣命名?

答案就在下圖:

注意上圖中的 did 表明通常過去時,will 表明通常未來時。

而後咱們百科通常過去式和通常未來時,而後如圖所示:

通常過去時:

通常未來時

看上圖的紅箭頭,did 表示通常過去時,時是指動做發生的時間,用在這裏,突出了鉤子的含義,一旦 mount 成功就執行此函數。是否是瞬間明白了,好了,will 同理。

啥也別說了,趕忙去好好看看初高中英語語法吧。

經過函數返回結果來命名

這是個小特性,好比 shouldComponentUpdate , 爲何 should 放在最前面。

由於這個函數返回的值是布爾值。那麼咱們能夠理解爲這是個問句,經過問句的形式來告訴咱們,這裏具備不肯定性,須要根據返回值來判斷是否更新。

關於問句的英語語法,老鐵們還要多翻翻語法書啊(淚)。

藉助工具

藉助谷歌翻譯

谷歌翻譯這個就不說了,你們都會

藉助 codelf

這是一個神器,用來搜索各類開源項目中的變量命名,來給你提供參考。

地址:unbug.github.io/codelf/

對應名字的 VSCODE 插件也有,具體怎麼用,小夥伴自行去了解吧。

如何避免函數命名的多義性和不可讀性

可能你給一個函數命名了,其餘人看到這個函數時,一臉懵逼,徹底不知道這命名的啥子東西喲,只能靠猜。

好比我從 ramda 源碼中找了一個函數,代碼以下:

var forEachObjIndexed = _curry2(function forEachObjIndexed(fn, obj) {
  var keyList = keys(obj);
  var idx = 0;
  while (idx < keyList.length) {
    var key = keyList[idx];
    fn(obj[key], key, obj);
    idx += 1;
  }
  return obj;
});
export default forEachObjIndexed;

複製代碼

這個函數叫 forEachObjIndexed ,看到這個命名,是否是一臉懵逼,反正我第一次看到是懵逼了,這啥子嘛,什麼鬼東西,而後我就去趴了下源碼,從源碼裏面的函數註釋中才知道是幹啥的,函數註釋以下圖:

看到沒,多詳細,固然,這是爲了輸出文檔用的,可是給了咱們一塊兒很是好的解決方法。那就是:

若是你實在想不到如何去命名,或者你本身已經知道這個命名很爛了,好比太長,好比很難理解,那這個時候你就別掙扎了。寫一個你以爲還 ok 的命名,而後把剩下的時間留給你寫註釋吧。好比 forEachObjIndexed 的第一部分的註釋就是對整個函數的總體介紹和說明。

若是你的函數命名很爛,那這個時候,函數的總體介紹和說明就顯得很是重要了。這部分你必定要作好,英語水平很差的話,那就老老實實寫中文。這部分作好了,這個函數你哪怕用兩行文字命名的,或者用了火星文命名的,也不要緊,問題不大。

函數命名的分類

最後說一說命名的分類,這是我我的的一些見解。

爲何我會說函數命名的分類呢,是由於咱們常常會看到函數會這樣命名(源碼中很廣泛)。好比:

- $xxx()
- _xxx()
複製代碼

這種帶各類前綴的函數名,看起來並很差看。這樣命名,在我我的看起來是很是彆扭的,可是爲何要有這種命名呢,其實這是前端的無奈之舉。

核心緣由就是 JS 語言不支持私有變量,致使只能使用 _ 或者 $ 來保證相應的對外不可見,經過治標不治本的方法來解決這個問題。

因此我把前端的函數命名分爲兩大類,以下:

第一類:不想暴露給外部訪問的函數(好比只給內部使用)

第二類:暴露給外部訪問的函數(各類功能方法)

我我的目前的觀點,大體也就這兩大類了。

PS:這裏我沒把 Symbol 初始化的函數命名考慮在內,好比以下代碼:

const ADD = Symbol('add')

[ADD](a, b) {
  console.log('a + b')
}
複製代碼

關於 Symbol 的用法,你們能夠自行了解,這種特例我就不考慮在內了。

PS:關於這個無奈之舉,在瞭解的更多的時候,會發如今前端,並無什麼方法(設計模式也好,hack 方法也好)能絕對的解決上面的問題,因此有時候你不得不使用 _ 等,由於當都不能解決這個問題的時候,那越簡單的方式越受歡迎,這就是現實。

總結

總結一下最佳實踐:

多學習初中高中英語語法,開源項目中的函數命名沒有那麼難理解,經過語法的學習和藉助工具,函數命名基本能夠解決,若是遇到沒法清晰描述所寫函數的目的的命名時,請務必給函數寫上良好註釋,無論函數名字有多長多難懂,只要有良好的註釋,那就是能夠接受的一件事情。畢竟你也不想命名的這麼難懂啊,可是能力有限,那就用漢語作好註釋吧,這樣的效果也是槓槓的。

如何經過良好的函數命名來提供函數的質量,我也說的差很少了,答案都在文字中,如何去借助工具,如何去理解英語中的命名語法,如何去經過多維度來增長命名含義的準確性和可讀性。簡單聊了下目前前端界函數命名的分類,你們自行體會和運用吧。

PS:一些都知道的點我就不說了,好比動詞+名詞,名詞+動詞,駝峯等,清晰描述函數的目的,這都不是痛點,痛點我都說了,最佳實踐也說了。

函數的註釋

咱們來談函數的註釋,註釋一方面提升了可讀性,另外一方面也能夠經過註釋去作一些其它的事情,好比生成在線文檔。一個高質量的函數,註釋少不了的,可是這並不表明全部的函數都須要註釋。富有富的活法,窮有窮的瀟灑,重要或者說複雜的函數,那就給個好註釋,簡單或者不重要的函數,能夠不給註釋或者給一個簡單的註釋。說空話沒有意義,咱們來看看目前函數的註釋都有哪幾種方式。

PS:這裏要注意我上面的用詞,若是你以爲這個函數命名很爛,那你就應該給一個好的註釋。

先說一些有名的npm包的一些註釋風格

就像大學裏面寫論文以前,都要閱讀不少文獻資料,咱們也同樣,咱們來看看幾個有名的 npm 包是怎麼玩註釋的。

egg.js 的註釋風格

從圖中,咱們看到 egg.js 的入口文件的註釋狀況,暫且不去判斷這是否是一種 doc 工具的註釋規則(不要在乎細節)。咱們就看一下其註釋特色,是否是發現和你腦海中的註釋風格又有區別了呢。這種入口文件的註釋特色,簡單整潔,這種思想是否是要吸取一波,之後你作開源項目的時候,這些思想均可以帶給你靈感。

繼續看下圖:

這是一個被抽象出來的基類,展現了做者 [Yiyu He] 當時寫這個類的時候,其註釋的風格。從這張圖中,咱們能學到什麼呢?有如下幾點:

第一點:構造函數的註釋規則,表達式語句的註釋規則。

第二點:註釋的取捨,有一些變量能夠不用註釋,有些要註釋,不要有那種要註釋就要所有註釋的思想。

再看兩張有趣的圖片:

看上面兩張圖的箭頭,指向的都是同一個做者 [fengmk2] , 咱們看他的函數註釋規則。體會一下不一樣,想一想爲何第一張圖沒有空格,第二種有空格,還有對返回的 this 的註釋,好比不少人習慣將 this 直接註釋成 Object 類型。

lodash.js

說到函數註釋,就不能不說到 lodash.js 。可是寫到這,我發現這塊要是加上去的話,第二篇的文字就又超了,那這裏就再也不說了,你們本身看看源碼分析一下吧(這操做真香)。

經過註釋生成在線文檔的思考

有人說註釋要很規範,方便給別人,好比用 jsdoc 等 。這裏我我的的見解是這樣的,對一些不須要開源的 web 項目,沒有必要用 jsdoc , 理由以下:

  1. 繁瑣,須要按照 jsdoc 規則來
  2. 我的認爲,jsdoc 有入侵性,文檔規則須要寫在代碼中。

這裏我認爲若是要寫註釋說明手冊,對於大型項目,我推薦使用 apidoc , 由於 apidoc 入侵性不強,不要求把規則寫在代碼中,你能夠把全部規則寫到一個文件中。具體使用方法,我就不說了,自行搜索相關資料。

可是通常小項目,沒有必要單獨寫一份 api 文檔。若是是開源的大型項目,那你要考慮的事情就更多了,首先須要有開源的官方網站,你會看到網上的一些開源項目官網好像很酷,其實這個世界上不缺的就是輪子,你也能夠很快的作出這樣的網站,下面咱們來看看是如何作到的。

首先咱們看一下 taro 源碼,會發現以下圖:

這裏就是生成一個靜態網站的祕密,執行這個 npm run docs 就能夠了。用到的是 docusaurus 包,不知道的能夠自行搜索。

而後這裏你看下圖:

從圖中能夠知道,文檔的內容,來源於 docs 目錄,裏面都是 md 文件,開源項目的文檔說明都在這裏。

固然也有把對應的文檔直接放到對應的代碼目錄下的,好比 ant-design 以下圖:

就是直接把文檔放在組件目錄下了。

從這裏,咱們能夠知道,目前流行的開源項目的官方網站是怎麼實現的,以及文檔該怎麼寫。你能夠說這和函數註釋沒有什麼關係,可是想一想好像又有點關係,這裏就很少言了,本身體會吧。

我我的的註釋習慣

下面說說我本人對函數註釋(只針對函數註釋)的一些我的風格或者意見。

分享 VSCode 關於註釋的幾個工具

  • Better Comments 給註釋上色
  • Document This 自動生成註釋
  • TODO Highlight 高亮 TODO ,並能夠搜尋全部 TODO

具體用法就不說了,下面是一張演示圖,自行去研究吧:


寫和不寫註釋的平衡

我我的的觀點是這樣的:

不影響可讀性,複雜度低,對外界沒有過分干涉的函數能夠不寫註釋。

表達式語句的註釋

函數內,表達式語句的註釋能夠簡單點,我通常以下圖所示,// 後面加簡要說明。

function add(a, b) {
  // sum ....
  let sum = a + b
}
複製代碼

TODO 註釋

function say() {
  // TODO: 編寫 say 具體內容
  console.log('say')
}
複製代碼

FIXME 註釋

function fix() {
  // FIXME: 刪除 console.log方法
  console.log('fix')
}
複製代碼

函數註釋

通常我分爲普通函數和構造函數。

普通函數註釋:

/** * add * @param {Number} a - 數字 * @param {Number} b - 數字 * @returns {Number} result - 兩個整數之和 */
function add(a, b) {
  // FIXME: 這裏要對 a, b 參數進行類型判斷
  let result = a + b
  return (result)
}
複製代碼

構造函數註釋:

class Kun {
  /** * @constructor * @param {Object} opt - 配置對象 */
  constructor(opt = {}) {
    // 語句註釋
    this.config = opt
  }
}
複製代碼

總結

從開源項目的代碼中能夠發現,註釋的風格多種多樣,有時候我本身不一樣項目的註釋風格也有點差異,可是我會盡量的去平衡註釋和不註釋,上面註釋的基本原則仍是要遵照的。

可是怎麼說呢,註釋這塊不存在銀彈。

函數的魯棒性(防護性編程)

你們都聽過防護性編程對吧,let it crash 。 咱們看一個段子,下圖:

看最後一句,測試測了那麼多場景,最後酒吧仍是炸了(哈哈哈哈哈哈怎麼回事?)。

因此,咱們能夠看出,防護性編程的核心就是:

把全部可能會出現的異常都考慮到,而且作相應處理。

可是我我的認爲,防護性的程度要看其重要的程度。通常來講,不可能去處理全部狀況的,可是提升代碼魯棒性的有效途徑就是進行防護性的編程。

一個項目的思考

我接手過一個需求,重寫(徹底重構)蘇寧易購微信小程序的登陸註冊綁定的功能,並將代碼同步到蘇寧其餘小程序(和其餘小程序的開發進行代碼交接並協助 coder 平穩完成版本過渡)。

這個項目重要性不言而喻,因爲用戶的基數很大,風險程度很高,須要考慮不少場景,好比:

  1. 支不支持線上版本回退,也就是須要有前端的 AB 版本方案(線上有任何問題,能夠快速切到舊登陸方案)

  2. 須要有各類驗證:圖形驗證碼、短信驗證碼、ip 、人機、設備指紋、風控、各類異常處理、異常埋點上報等。

  3. 代碼層面的考慮:經過代碼優化,縮短總的響應時間,提升用戶體驗。

  4. 如何確保單個節點出問題,不會影響整個登陸流程。

你會發現,須要考慮的點不少,如何去合理的完成這個需求仍是比較有難度的。

PS: 關於第四點的如何確保單個節點出問題,不會影響整個登陸流程,文末有答案。

下面我就關於函數魯棒性,說一說我我的的一些見解。

前端函數魯棒性的幾種方式

入參要魯棒性

ES6 的到來後,函數的入參寫法已經獲得了質的提升和優化。看下面代碼

function print(obj = {}) {
  console.log('name', obj.name)
  console.log('age', obj.age)
}
複製代碼

print 函數,入參是 obj 經過 obj = {} 來給入參設置默認的參數值,從而提升入參的魯棒性。

可是你會發現,若是入參的默認值是 {} ,那函數裏面的 obj.name 就會是 undefined ,這也不夠魯棒,因此下面就要說說函數內表達式語句的魯棒性了。

函數內表達式語句要魯棒性

繼續上個例子:

function print(obj = {}) {
  console.log('name:', obj.name || '未知姓名')
  console.log('age:', obj.age || '未知年齡')
}
複製代碼

若是這樣的話,那你會發現表達式語句就變得比較魯棒性了,可是還不夠好,這樣寫不夠抽象,咱們換種方式稍微把表達式語句給解耦一下,代碼以下:

function print(obj = {}) {
  const { name = '未知姓名', age = '未知年齡' } = obj
  console.log('name:', name)
  console.log('age:', age)
}
複製代碼

這樣的話,看起來就感受好多了,其實還能夠再抽象,好比吧 console.log 封裝成 log 函數,經過調用 log(name) ,就能完成 console.log('name:', name) 的功能, 這裏就再也不說了,自行研究吧。

函數異常處理的兩個層面

上面的那幾個點,我我的認爲能夠歸類到一個方案層面去,那就是:

防患於未然,從一開始就不要讓異常發生。

可是不要忘了,總會有萬一,還有一個方案層面要去考慮,那就是:

異常仍是出現了,該怎麼去處理出現的異常。

下面兩個層面已經肯定了,那如何去更好的處理各類異常,提升函數的魯棒性呢,我我的有如下幾點見解。

推導一下 try/catch 的原理

有不少人不清楚怎麼去用 try/catch 。這裏我來按照我我的的看法,來推一下其原理吧,首先 js 是運行在 node.js 提供的運行時環境中的,而 node.js 是用 C++ 寫的。C++ 是有本身的異常處理機制的,也是有 try/catch 的 。那就說明 jstry/catch 的底層實現是直接經過橋,調用 C++try/catch

C++try/catch 具備的一些特性,你們能夠自行去了解一下,好比其中就有一個特性是這樣的:

try/catch 只能捕捉當前線程的異常。

因此這也就很好的解釋了,爲何 JStry/catch 只能捕捉到同步的異常,而對於異步的異常就無能爲力了(由於異步是放在另外一個線程中執行的)。

這裏是個人推導,不表明確切答案。

這裏我推薦一篇博客:

C++中try、catch 異常處理機制

有興趣的能夠看看。

合理的處理異常

這裏有幾個方法:

第一個方法:若是是同步的操做,能夠用 throw 來傳遞異常

看下面代碼:

try {
  throw new Error('hello godkun, i am an Error ')
  console.log('throw 以後的處代碼不執行')
} catch (e) {
  console.log(e.message)
}
複製代碼

首先咱們要知道 throw 是以同步的方式傳遞異常的,也就是 throw 要和使用 throw 傳遞錯誤的函數擁有相同的上下文環境。

若是上下文環境中,都沒有使用 try/catch 的話,可是又 throw 了異常,那麼程序大機率會崩潰。

若是是 nodejs ,這個時候就應該再加一個進程級的 uncaughtException 來捕捉這種沒有被捕捉的異常。一般還會加上 unhandledRejection 的異常處理。

第二個方法:若是是異步的操做

有三種方式:

  1. 使用callback ,好比 nodejserror first 風格

  2. 對於複雜的狀況可使用基於 Event 的方式來作,調用者來監聽對象的 error 事件

  3. 使用 promiseasync/await 來捕捉異常

如今的問題是,怎麼去選擇哪一個方式呢?有這幾個原則:

  1. 簡單的場景,直接使用 promiseasync/await 來捕捉異常

  2. 複雜的場景,好比可能會產生多個錯誤,這個時候最好用 Event 的方式

第三個方法:若是既有異步操做又有同步操做

怎麼辦呢?這個時候,我我的認爲,最好的方式,就是使用最新的語法:async/await 來結合 promisetry/catch 來完成對既有同步操做又有異步操做的異常捕捉。

第四個方法:處理異常的一些抽象和封裝

對處理異常的函數進行抽象和封裝也是提升函數質量的一個途徑。如何對處理異常進行抽象和封裝呢?有幾個方式能夠搞定它:

  • 第一個方式:對 nodejs 來講,一般將異常處理封裝成中間件,好比基於 express/koa 的異常中間件,一般狀況下,處理異常的中間件要做爲最後一箇中間件加載,目的是爲了捕獲以前的全部中間件可能出現的錯誤

  • 第二個方式:對前端或者 nodejs 來講,能夠將異常處理封裝成模塊,相似 Event 的那種。

  • 第三種方式:使用裝飾器模式,對函數裝飾異常處理模塊,好比經過裝飾器對當前函數包裹一層 try/catch

  • 第四種方式:使用函數式編程中的函子( Monad )等來對異常處理進行統一包裹,這裏 的 Monadtry/catch 在表現上都至關於一個容器,這是一個至關強大的方法。從 Monad 能夠擴展出不少異常處理的黑科技,可是我建議慎用,由於不是全部人都能看懂的,要考慮團隊的總體技術能力,固然一我的的話,那就隨便嗨了。

合理的處理異常,須要能肯定使用哪種方式來處理異常,我大體也說了具體的選擇狀況,這裏我推薦一篇博客:

Callback Promise Generator Async-Await 和異常處理的演進

目前我見到的講的最全的處理異常的博客,但我這裏說的都是我認爲比較重要的主要的點,二者仍是有明顯區別的,你們融合一下吸取吸取吧。

如何確保單個節點出問題,不會影響整個登陸流程

好比登陸流程須要4個安全驗證,按照一般的寫法,其中一個掛了,那就所有掛了,可是這不夠魯棒性,如何去解決這個問題呢。這裏我提一下,可能不少人都不會注意到。

主要方案就使用將 promise 的鏈式寫法換一種方式寫,之前的寫法是這樣的:

僞代碼以下:

auth().then(getIP).then(getToken).then(autoLogin).then(xxx).catch(function(){})
複製代碼

通過魯棒調整後,能夠改爲以下寫法:

僞代碼以下:

auth().catch(goAuthErrorHandle).then(getIP).catch(goIPErrorHandle).then(function(r){})
複製代碼

通過微調後的代碼,直接讓登陸流程的魯棒性提高了不少,就算出錯也能夠經過錯誤處理後,繼續傳遞到下一個方法中。

我我的對異常處理的見解

我我的認爲對異常的處理,仍是要根據實際狀況來分析的。大概有如下幾點見解:

要考慮項目可維護性,團隊技術水平

我曾在一個需求中,使用了諸如函子等較爲抽象的處理異常的方法,雖然秀了一把(做死),結果致使,後續這塊的需求改動,還得我本身來。嗯,就是這麼刺激,由於同事不熟悉函數式編程。

要提早預估好項目的複雜性和重要性。

好比在作一個比較重要的業務時,一開始沒有想到異常處理須要這麼細節,並且通常初版的時候,需求並無涉及到不少異常狀況處理,可是後續需求迭代優化的時候,發現異常狀況處理是如此的多,直接致使須要重寫異常處理相關的代碼。

因此之後在項目評估的時候,要學會嘗試根據項目的重要性,來提早預留好坑位。

這也算是一種面對將來的編程模式。

總結

關於函數的魯棒性(防護性編程),我介紹了不少東西,基本上是前端或者是 nodejs 處理異常的常規方法吧。處理異常不是一個簡單的活,工做中還得結合業務去肯定合適的異常處理方式,總之,多多實踐出真知吧。

備註

  • 本篇文章閱讀起來就比較輕鬆了,難度不大,細細體會一下會有一些收穫的。
  • 可能講解的不全,若是有什麼遺漏的,歡迎在評論區分享,一塊兒進步。
  • 魯棒性這塊,我沒有提單元測試,字數不夠寫了,再寫文章又很長了,單元測試我只推薦 Jest ,按照官網文檔來,本着函數式編程的思想,問題不大。

往屆精品文章

能夠這麼說,讀了這篇文章,你的 gitgerrit 就沒有什麼問題。

初中高級的 git 和 gerrit 技巧【大型項目實戰總結 && CR 經驗】


關於如何閱讀 npm 包源碼的故事。

不敢閱讀 npm 包源碼?帶你揭祕 taro init 背後的哲學

彩蛋

最近剛寫的一篇文章,發現沒什麼閱讀量,可是我以爲我寫的很好啊,這篇文章絕對會對絕大多數前端工程師有所啓發和幫助。

宣傳一波,想啓發更多還在路上的前端小夥伴:

新時代下前端工程師的推薦書籍和必備知識

交流

加上本篇,這個系列已經寫了兩篇了,我計劃三篇搞定,可是看這狀況,後面都是硬貨,很難 7000 字之內搞定呀,後續幾篇搞定,我再 ob 一下吧。

小夥伴們能夠關注個人掘金博客或者 github 來獲取後續的系列文章更新通知。

掘金系列技術文章在 github 上彙總以下,以爲不錯的話,點個 star 鼓勵一下,我將 使命必達 ,持續輸出精品文章。

github.com/godkun/blog

我是源碼終結者,歡迎技術交流。

也能夠進 前端狂想錄羣 你們一塊兒頭腦風暴。有想加的,由於人滿了,能夠先加我好友,我來邀請你進羣。

風之語

最後:尊重原創,轉載請註明出處哈😋

相關文章
相關標籤/搜索