一個前端工程師看完《代碼大全》後的二三總結

題記: 書中自有黃金屋,書中自有顏如玉。 就好像 one piece ,等待着咱們去發現,找到。不是全部的地方都有 one piece (書的每一章每一頁),也許在某處,有一段回味無窮的話,等待着咱們去發現。一些人可能錯過了,一些人可能找到了,這也許就是讀書的魅力吧。前端

寫在最前

讀了不少技術方面的書籍,這本 《代碼大全》 值得我去爲它寫一篇總結,這也是我在掘金寫的第一篇書籍讀後感,我很是提倡多去閱讀書籍。 git

image

由於,我我的以爲,每個出書的人,在撰寫書的過程當中,都投入了不少不少的時間和精力,他們會盡量的把本身收穫的經驗、總結等都以儘量的通俗易懂的方式在書中表達出來,這是一種本能的行爲,就好像在遊戲中達成一個成就,出一本好書,能夠說是每一個出書人的初衷。程序員

因此我給那些出書的人都點個贊吧,也許書中有不少地方咱們以爲是照搬啥的,沒有養分啥的。可是以個人經驗來講,只要是公認的好書,基本上在某一章,甚至某一段,必定會帶給你柳暗花明或者說是茅塞頓開的驚喜感。就比如玩拳皇,一頓搖把加狂按,忽然放出大招時的無以言表的驚喜和開心。。。嗯~~(歷來沒按出來過)&¥&¥#。。。。。算法

開始個人表演

Just enough, 其餘讚美的話就很少說了(讚美好書的詞語省略800字),下面準備步入正軌了。代碼大全這本書,我好久之前就買了,當時還沒入圈😂,看了一部分,也作了一些筆記,寫在了小本本上,自從入圈以來,就沒有看過了,最近幾天之前端工程師的身份從新完整的過了一遍,發現了新大陸,找到了幾處one piece。對溫故而知新的理念不能再贊同了,在此把個人一些總結和收穫分享出來,就像此書的一個讚譽那樣寫到:編程

每一個程序員都改讀讀這本傑出的書籍。設計模式

趕快開始吧。。。

《代碼大全》總共有944頁內容,很實在,裏面涉及到的知識點不少,主體代碼是以Java和C++爲主。代碼形式其實都不重要,重要的是要表達的思想。對於前端工程師來講,我總結了如下幾個方面的知識,開始吧。安全

條件語句switch用對了麼

不少時候,咱們在用switch語句的時候,對如何使用default,並無一個明確的原則,有時候default下,什麼都不執行,有時候default下,會去執行最後一種可能。還有有時候case的狀況不少,咱們並無在乎排序問題。等等其餘,其實這在編程中都是一種很差的行爲。那麼來,怎樣纔是正確編寫switch語句的姿式呢?請看以下:微信

tip1——讓default幹它該乾的事情

原則上,default下,不要寫最後一種可能,由於default設計出來的目的,實際上是爲了捕捉錯誤的。因此業務中出現的全部狀況都應該用case去捕捉,這也體現了使用case後面的label去說明這是哪一種狀況的做用。而default後面沒法加label說明,也就失去了對可能狀況的說明。舉個栗子,在前端中,若是對請求返回的狀態碼進行判斷,能夠寫成以下形式:前端工程師

switch(code) {
  case: '1':
    console.log('成功')
    break
  case: '0':
    console.log('失敗')
    break
  default:
    dealError()
}
複製代碼

從上面代碼能夠看出,default不要作任何有正常case的操做,它專門用來和檢測和處理錯誤,固然若是業務中把某些case都當成錯誤的話,也能夠統一寫到default中。閉包

tip2-讓case變的簡潔、有序和高效

1: 若是case的狀況不少,那就要按照出現頻率去從上到下排列,這樣switch語句代碼的總體效率會提升。

2: 若是case的一個狀況,語句太多,那就果斷封裝成子程序來調用。避免在一個case下寫不少語句,讓case變得難以理解。

如何判斷代碼的複雜度

你們可能會本能的想到大O方法啥的,對前端來講,大O那種模式不適用,大O是衡量算法的複雜度。全全裏面提到了一個頗有趣的判斷複雜度的方法,叫作 Tom McCabe 方法,該方法很簡單,經過計算函數中 決策點 的數量來衡量複雜度。下面是一種計算決策點(結合前端)的方法:

  1. 1開始,一直往下經過函數
  2. 一旦遇到if while for else或者帶有循環的高階函數,好比forEach map等就加1
  3. 給case語句中的每一種狀況都加1

好比下面代碼:

function fun(arr, n) {
  let len = arr.length
  for (let i = 0; i < len; i++) {
    if (arr[i] == n) {
        // todo...
    } else {
        // todo...
    }
  }
}
複製代碼

按照Tom McCabe方法來計算複雜度,那麼這個fun函數的決策點數量是 3 。知道決策點數量後,怎麼知道其度量結果呢?這裏有一個數值區間判斷:

數量區間 度量結果
0-5 這個函數可能還不錯
6-10 得想辦法簡化這個函數了
10+ 把這個函數的某一部分拆分紅另外一個函數並調用他

從上面的判斷依據能夠看出,我上面寫的代碼,數量是3,能夠稱爲函數還不錯。我我的以爲這個判斷方法仍是很科學和簡單的,能夠做爲平時寫代碼時判斷函數需不須要重構的一個考慮點,畢竟一個函數,一眼掃去,決策點數量大體就知道是多少了,很好計算。

你心中的抽象和封裝以及模塊是什麼?

怎麼說呢,其實有些時候,咱們不知道,不表明咱們不會,不少時候是這種狀況:我真的看過這方面的知識或者我確實真的研究過這些,可是確實是忘了😂。因此此刻,你看到這裏的時候,就贊贊收藏吧(嘻嘻)。

我以爲這種偏概念的東西,每一個人均可以回答的不一樣,可是隻要你真正理解了其中的本質或者說是一種答案,其實這就夠了。這裏我說一下我本身對抽象和封裝以及模塊的見解。

抽象在我眼裏,實際上是把混亂變成有序,把零散變成總體。咱們常常說,要把業務代碼抽象成組件,作成組件化。其實就是把零散變成總體,把混亂變成有序的過程。舉個荔枝:

好比說咱們項目中尚未作組件化,彈窗這個功能,仍是各類頁面裏寫本身的彈窗代碼。如今咱們須要重構,把這個零散和混亂的彈窗,抽象成一個總體有序的彈窗組件。那麼,咱們來看看原來的彈窗代碼,發現如下問題:

  1. 代碼重複,同時零散分佈在各個頁面中。
  2. 代碼混亂,沒有統一的入口,沒有統一的顯示邏輯。

如何解決呢,這個時候就須要對彈窗進行抽象了,如何抽象,一個辦法,就是解決掉重複和混亂,若是解決掉了,就能夠表示抽象已經初見成效了。

這裏提一下ADT,這是面對對象的編程模式中的類的基礎,叫 Abstract Data Type ,也就是抽象數據類型,可是我不想用這個,這裏我借鑑DOMBOM形式,我把它叫作 ADM。 全稱:Abstract Data Model 也就是抽象數據模型。不知道可不能夠這樣玩,可是我以爲問題不大,嘻嘻。沒有意見,那下面我繼續操做了。

咱們須要把彈窗可能用到的數據所有收集起來,而後將這些數據歸屬於一個對象模型,爲了形象比喻,我把它叫作彈窗人,擁有生命。這個彈窗人的實體是由這些數據組成的,OK,這樣就把以前零散的數據所有集合在一個實體上了,也就是把零散變成總體。請看下面這句話:

沒有封裝時,抽象每每很容易打破。

若是我只是抽象了,把零散變成總體了,可是卻沒有把混亂變成有序,那麼抽象就會被打破,就比如彈窗人擁有的數據,這裏我花式比喻一下。好比彈窗人擁有100萬,關鍵100萬仍是公開的,結果悲劇了。

不少人都想向他借錢,若是彈窗人事先不指定好借錢的方式。那麼來就會很刺激了,朋友A微信問他借錢,朋友B支付寶向他收款,社會混子直接電話向他威脅借錢,更有牛逼的,直接強行把他綁架了,而後刀光劍影伺候。彈窗人內心苦啊,難受。

終於彈窗人大悟了,事先指定了借錢的方式,只能先經過短信,其餘借錢方式一概拒絕,而且要通過他的贊成,同時堅定不公開本身的財產。今後之後,沒有人知道彈窗人有多少錢,還覺得是個窮逼(彈窗人是程序員),就算想借錢,也只能經過短信告訴彈窗人我想借多少錢,而後贊成後,才借給你。今後,彈窗人過上了幸福快樂的生活了。

上面是即興寫出來的栗子。突然發現我還挺有想象力的。給本身 0110 0110 0110,其實你讀完大概就知道我想表達什麼思想了。這就是封裝的目的,不只是前端領域封裝的目的,同時也是全部面對對象領域封裝的目的。若是有例外,,捂嘴,,沒有。。

從上面咱們能夠看出,抽象和封裝存在密不可分的聯繫。仔細去體味上面的故事,你會發現咱們在讓混亂變成有序的的時候,實際上是在讓可訪問性變得儘量的低,也就是封裝自己的原則:

封裝的原則是讓可訪問性儘量的低。

不少人雖然知道封裝是爲了下降可訪問性,可是殊不知道爲何,可能也知道爲何吧?這裏中斷一下,跳個番外。

在貴(程序員)圈裏有個很好玩的現象,那就是我知道某一個知識的目的,可是卻說不清原理,或者說我也查過,試圖去了解這個原理,可是老是會有一種朦朦朧朧的不懂感圍繞着本身。而後內心 ob :先就這樣吧,後面再說😂。而後就不能透徹的理解。我咋知道這些的,由於我有時也有這種感受,感受是沒法避免的。能作的就是在往後別忘了把當時朦朦朧朧的困惑解決掉。

中斷結束,繼續胡謅🙂,我有多少錢你不能知道,知道的話,個人錢就會變得不安全。你只能經過固定的渠道來訪問我,還不能直接訪問數據,須要通過個人贊成,才能進行相應的操做。其實可訪問性這個已經解釋的很透徹了。好了,不解釋了。


那麼前端的模塊化是什麼意識呢 ?

其實徹底能夠理解爲組件化。模塊化,顧名思義想表達的就是想要總體的意識,既然總體,那就要封裝,封裝前就須要進行抽象,而後又迴歸本質。那麼目前前端是怎樣實現模塊化的呢?

JavaScript 是以面向對象爲基礎的編程語言,至少有句話說的是:在JavaScript中,一切皆對象,其實能夠這麼說,可是JavaScript有個很尷尬的一點是,沒有類,雖然如今有類,但也只是一種語法糖。這裏不考慮TypeScript。那它怎麼實現模塊化呢?

實現編程語言中的類的抽象模型,也就是我上面說的ADM。在我看來,在不使用class語法糖的狀況下,前端的模塊化的實現原理就是經過使用JavaScript的私有變量特性和閉包特性來實現模塊化。ES5的時候,JS是沒有塊級做用域的,只有全局變量和私有變量,若是連私有變量也沒有的話,那JavaScrript也就GG了,因此我很好奇當初設計JS的時候,都採用了類C的語言設計風格,爲何沒有實現塊級做用域呢,是否是當時以爲JS並不須要這麼多功能啊😂。既然有私有變量,那麼就會有私有屬性和私有方法,畢竟本質上都是變量。具體代碼我就不貼了,寫個僞代碼吧:

function fun() {
    v1 是私有屬性
    f1 是私有方法
    // 返回一個對象
    return {
      v2 是共有屬性
      f2 是共有方法 {
          共有方法裏面能夠訪問和修改 私有屬性和私有方法
          處理 v1
          處理 f1
      }    
    }
}
複製代碼

如何編寫高質量的函數

全全(指代碼大全,下同)裏寫的是如何編寫高質量的子程序,其實JS函數就是子程序(99%正確)。全全裏說的高質量的一些總結有些不適用JS。 這裏我融合一下本身的一些經驗和總結。請往下看:

有沒有想過爲何要發明函數這個東西?

做爲前端工程師,對於這個問題,仍是10分重視的。頭偏向45度方向,在腦殼中想個10秒鐘,可能還會眨幾下眼睛,不要問我爲何知道你的狀態,由於XX。其實你們都能說出一些本身的見解,不須要答案,可是我仍是想給一個看起來逼格很高的answer。那就是:

函數是迄今爲止發明出來的用於節約空間和提升性能的最重要的手段。 注意,沒有之一。那麼咱們如今能夠肯定的是: 它是用來節約空間和提升性能的。 這樣的話,若是咱們不去優化函數,寫出高質量的函數,豈不是失去了它存在的意義。如今面臨的最關鍵的問題就是:如何去優化函數,寫出高質量的函數?

if (str === 'hello world') {
    console.log('hello world')
} else {
    console.log('666')
}
複製代碼

上面是一段代碼,若是在其餘地方要用,就必須在用的地方把上面這段代碼原封不動的重複編寫一遍,可是有了函數,就能夠將其放到函數內,而後經過函數print(str)來調用,在其餘地方只須要寫這一行就能夠了,優勢很明顯。

如何寫出高質量的函數。其實就這一點就能夠寫一篇文章了,這裏我不詳細說明闡述了,隨便提幾點吧,高質量的具體實現之後再說😂。

從娃娃抓起,起一個好名字很重要

不能輸出起跑線上,考慮的點有如下幾點:

  1. 名字要能清晰的描述此函數的目的
  2. 統一好書寫形式。好比統一使用下劃線、駝峯等命名形式
  3. 統一好單詞組成形式,是名詞+動詞,仍是動詞+名詞

優雅的傳遞和處理參數

  1. 參數較多,可使用參數對象模式
  2. 參數不固定,好比動態參數,可使用ES6的擴展符
  3. 使用ES6的參數默認值來處理參數默認取值問題

設計函數時的一些考慮

  1. 避免函數代碼重複
  2. 縮小函數代碼規模
  3. 增長函數魯棒性
  4. 註釋風格要統一
  5. 儘量的保持pure特性,也就是冪等性,這樣能夠最大限度的防止後期的各類莫名其妙的bug

關於跨度和生存時間

變量有一個本身的屬性,叫存活時間,在編程語言中,要儘量的縮短變量的存活時間。這樣的話,若是咱們用跨度和生存時間的概念來看全局變量,就會發現爲何要避免使用全局變量,由於全局變量的跨度和生存時間都很長。

彩蛋:JS 爲何要避免全局變量,其實一個主要緣由是 JS 的代碼執行,是由裏向外的,若是是全局變量的話,那麼這個查找的時間就比較長,因此在 JQuery 等源碼中,直接將 window 當成參數傳到函數中,是有它的道理的,能夠提升代碼性能。

關於布爾表達式的一個不爲人知的點

看以下代碼

let i = true 
if (i = true) {
  // todo...
}
複製代碼

能夠看到,若是你在業務代碼中,不當心少寫=號,變成上面這段代碼,那麼它是不會報錯的,可是要是寫成這種形式:

let i = true
if (true = i) {
  // todo...
}
複製代碼

就會報錯了,由於若是表達式左側不是變量的話,解釋器會報錯。因此在JS編程中,能夠把常量放在等號左側。這是一個很小衆的 tip,並且在前端來講,給項目加個 eslint 就能夠徹底避免這種錯誤了,若是沒有寫 eslint,能夠考慮一下這個 tip,若是用了代碼檢查工具,那就當下酒菜吧。

來點佛學的知識

如何修改bug、代碼缺陷

這個。。。五彩臉?對於及時保存源碼等這種建議就不提了,畢竟 git 操做穩的一比,提一下其餘方面的雞湯吧:

  1. 放鬆一下:嗯。。。。。。
  2. 修改代碼時必定要有恰當的理由。理由要充分,有理有據。
  3. 一次只作一個改動

備註

  1. 設計模式這個就不總結了,東西不少,須要拿出來單獨說。
  2. 一些系統級的總結也不說了,和前端關係不大。
  3. 對於遞歸的注意事項也不說了,前端用到遞歸的狀況很少。
  4. 對於僞代碼編程,之後單獨提
  5. 對於編寫高質量的函數,總結的簡單,由於涉及到的東西不少,這裏我更想提的是最本質的一些知識,好比被創造出來的目的,有時候你寫了不少函數,都沒有想過這個問題,如今看到了,心中會有種豁然開朗的感受吧。

文末的可愛聲明: 若是轉發或者引用,請貼上原連接。本文就比如一本書,可能有一些地方對於你來講是沒有養分,可是隻要有那麼一段,或者一句讓你感到驚喜的地方,我就很開心了。文章可能有一些錯誤,歡迎評論指出,也歡迎一塊兒討論。文章可能寫的不夠好,還請多多包涵。多一點貢獻,多一分開心~

相關文章
相關標籤/搜索