1. 程式人生 > >寫給自己,梳理一下我現在對前端知識結構的理解

寫給自己,梳理一下我現在對前端知識結構的理解

今天想著做一件事情,給自己的收藏夾分類。結果做著做著,發現這個任務的工作量超乎我的想象。有一些文章,可能很難界定說,它是哪一類的;而且自己還沒有特別去梳理自己對前端知識結構的理解,使得在分類的時候層級也有些模糊。所以在這裡梳理一下自己理解中的知識結構。

這既是一篇總結,也是一篇指南,有些地方我自己親身經歷可能豐富一點,就說的多一些;有些地方自己沒什麼實踐,就少說話,簡單提一提,免得貽笑大方。

還有一點,這份指南中,個人色彩其實很重。有些學習方法上的建議,我都是從自己的經歷出發的,但肯定不適合所有人。比如我喜歡淺閱讀,看很多東西,需要用到的時候,心裡有個大概,然後再深入研究,用到專案中。但我也遇到過一些喜歡深閱讀的同學,他們看到一個東西就喜歡深入學習,舉一反三。認識自己的特點並且選擇適合自己的方法非常重要,就像小馬過河的故事一樣。

JavaScript

就語言本身來說,JavaScript值得深究的地方不多。很多同學在最開始入行的時候(就像我),可能根本不懂就已經開始開發了。雖說在開發中踩坑,在踩坑中理解也未嘗不可,不過我現在覺得,一開始先了解一些很常用的語法,還是很重要的。

我對前端的JavaScript學習,列出了這樣的結構:

  • 語法
  • 框架與類庫
  • 設計模式
  • 函式式
  • 底層
  • 發展

接下來就各個層面進行闡述:

語法

關於語法,JavaScript中值得注意的大點,其實也不是特別多,大概就以下幾方面是比較常用的:

  • 變數提升
  • this 指向
  • 深複製和繼承的寫法
  • 閉包
  • 高階函式
  • 非同步與事件模型

關於語法,現有的資料其實很多。從我自己的學習經歷來看,我是先簡單過一遍《JavaScript高階程式設計》,有一個大概的理解,另外準備一本《JavaScript權威指南》當字典(高程其實也是字典)。建議深入閱讀

《You Don't Know JS》這一系列,寫的真心非常好。

其他資料也推薦一些供大家選擇:

框架與類庫

其實很多時候,能聽到將jQuery稱為框架的這種聲音,我覺得是不妥的。目前我覺得,常用的第三方包大概兩種,框架(framework)和庫(library)。我界定兩者的標準是:框架會影響到你專案的目錄結構、程式碼結構以及程式設計模型這些設計相關的東西,而庫則僅僅是提供了某些或某類操作的簡潔封裝方便呼叫。框架中包含的概念,一般要比庫複雜的多,所以我覺得jQuery是一個庫,提供了關於DOM操作,Ajax請求等一系列常用操作的簡潔封裝,而算不上框架。

就我所知,現在比較常見的框架如下:

  • React
  • Angular 2
  • Angular 1
  • Ember
  • Polymer
  • Vue
  • Riot

其實還有rxjs / cycle.js這個純粹的函式式的框架活躍著,ng2使用了rxjs,React也從中借鑑了思想(包括在redux中用rxjs處理非同步Action),但純粹用這一套的專案,應該還是demo多吧。

我對於框架學習的態度是:將一個真正用到專案中,瞭解一下其他框架的特點和主要思想(當然時間足夠且不怕忘的話,多來幾個也沒問題,還是那句話,根據自己特點來)。其實哪怕框架過時了,思想也還是有價值的。之前和@RizzleCi聊的時候,她說覺得現在就很像jQuery統治世界之前的樣子。現在來看,最終誰會勝出還是個未知數。

然而對於很多同學來說,可能很難去在專案中學習一個框架:自學只能敲demo,專案不熟不敢用。確實,demo的複雜度不足以讓你從工程的層次去學習框架,而這一點我的建議就是,借用公共的API進行開發。我推薦使用GitHub和豆瓣(並不是廣告),其他文件全面穩定且複雜度足夠的API也沒有問題。我認為只要你開發了一個足夠複雜的前端專案,就能切身體會到框架所帶來的優缺點。(其實只要解除跨域限制,哪的API都可以用,方法就是使用代理軟體,後面講開發與除錯的時候會具體說)

上面說的這些框架,更準確的來說,其實是專注於將表現和資料分離的框架。其實還有很多框架不在這一類,如針對遊戲開發的Egret。(遊戲這個領域我沒有接觸過,點到為止)

說到庫的話,我覺得大概有兩類:一類相對來說通用一些,如jQuery、lodash;另一類相對專用,如針對資料視覺化的D3、Highcharts,針對3D圖形的three.js,甚至比較簡單的如針對時間處理的moment等等。整體來說,庫的上手程度不高,比如jQuery,理解清楚被jQuery的$符包裹的物件和普通DOM的區別及其相互轉化,剩下的應該就只有查文件了。

相關推薦:

設計模式

對設計模式的使用,應該是一種經驗的體現。由於個人經驗缺乏,我現在對設計模式用的很少,僅僅簡單實踐過像策略模式、裝飾者模式這些。我認為設計模式應該是要用心去學習的一個點,也是提升能力的一個有效途徑。

相關資料:

函式式

前端的函數語言程式設計,應該是在近年來火起來的。其實在高階程式設計上,就對JavaScript的函數語言程式設計有所涉及。函數語言程式設計的起源要從λ演算說起,有興趣可以查閱相關資料。就我目前的感覺來說,在JavaScript中應用函數語言程式設計更像是一種高階技巧,這種技巧一般都會涉及到閉包和高階函式,反正我覺得,真心好用。

舉一個簡單的例子:寫一個before函式(before(count, function)),返回一個函式,呼叫不超過count次。 當count已經達到時,最後一個函式呼叫的結果將被記住並返回。

比如,我傳入這樣一個函式:

function log() {
  console.log.apply(console, arguments)
  return arguments[0]
}

before函式獲得只能執行3次的log:

var log3 = before(3, log)

log3(1)   // 1
log3(2)   // 2
log3(3)   // 3
log3(4)   // 什麼都沒有log

想一想,你會怎麼實現這個before函式。(答案傳送門

還有一些非常常用的函式節流技巧(throttledebounce)、封裝一些原生函式(如fetch),都會用到這相關的技巧。在ES7中,提供了Decorators相關的語法,讓你更方便的使用這些技巧。(這其實就是JavaScript中的裝飾者模式實踐)

許多框架在設計上借鑑了函式式的技巧,比較明顯的就是Redux,包括在Redux的原始碼中,也遍佈各種函式式的思維。rxjs更是將這種思維貫徹到了一個極致。我覺得將來rxjs包括cycle.js肯定會在框架中佔據一席之地,目前來說,至少RxJava發展的還是挺好的。

推薦:

底層

JavaScript能有今天的發展跟V8是脫不了關係的。很多講解JavaScript優化的文章,都會提到V8相關的實現。

不過我覺得,對於V8這一層面的東西,離前端還是有點遠了。目前我在瀏覽器開發,沒遇到過什麼效能上的大問題,學習V8原始碼,也不算是核心痛點。推薦幾篇相關文章:

發展

其實很想吐槽一下,現在的JS,一年一個版本,太可怕了。

當然,確實提供很多非常好用的語法(糖),比如class、解構、箭頭函式這些,我是挺喜歡用的。

另外一支很有勢頭的發展就是TypeScript,給JavaScript加入了強型別,使其更易於開發大型專案(介面的規範與更好的錯誤提示)。AngularJS 2已經全面擁抱TypeScript了,螞蟻金服的Ant-Design也已經切換到了TypeScript,可見其提供的特性還是很有吸引力的。在微軟推出了VS Code之後,TypeScript也有了官方的編輯器,值得一試。

在使用這些新特性的時候,一般都會用到類似babel這種轉換工具。關於這類工具的介紹,會在下面講開發與除錯的時候提到。

HTML & CSS

很多前端同學應該都是從這個地方入的坑吧。關於HTML和CSS的技巧,我覺得現在自己已經在某種程度上生疏了,畢竟很久沒有自己寫過了。

其實這個領域曾經帶給我很多樂趣,黑科技在某種程度上講要比JavaScript多很多,而且也是和瀏覽器相容的鬥爭最緊張的地方。如果想了解一些黑科技的話,建議閱讀張鑫旭的部落格,讀下來肯定會很有收穫。

下面是我覺得很有意思的幾篇文章:

學習CSS的話,推薦下面這些材料:

其他資料推薦:

開發與除錯

準備好了基礎知識,讓我們簡單瞭解一下開發與除錯相關的東西。在這一部分中,工具發揮著很大的作用。

我將按照如下順序闡述這一部分:

  • 規範
  • 構建
  • 除錯
  • 協同
  • 測試
  • 效能

規範

沒有規矩不成方圓,寫程式碼的時候團隊肯定要有一套規範。也有許多團隊將他們的規範拿了出來,比如:

其他團隊的規範未必適合自己,只要團隊成員達成共識,就是好的規範。

在程式碼commit之前進行規範的檢測是一個比較合適的時機,npm提供了一個叫做pre-commit的包,結合eslint-config-airbnb,可以搭建一套用於質量保證的東西出來。

相關資料:

構建

構建一般是使用webpack來進行,依靠各種強大的loader,可以完成一系列功能。強烈建議結合npm script管理專案的命令。

相關資料:

除錯

我最常用的工具應該就是Chrome Dev Tools了:

另外就是前面提到過的代理工具,Chrome外掛Proxy SwitchyOmega配合fiddler / charles,進行線上除錯。如果代理的自定義需求比較高,工具的正則滿足不了,可以嘗試自己寫一個nodejs程式,用http-proxy這個包來將資源代理到本地。

協同

推薦使用git,畢竟GitHub對於開發者已經如同簡歷、名片一般。

測試

測試是對程式碼質量的保證,不過說來慚愧,我就沒有比較好的測試習慣(這也是我打算培養的一種習慣)。

我對測試重要性的認識來源於在OJ上刷演算法題,很多時候丟擲一個WA(Wrong Answer)就什麼都沒有了,一時間就不知道從何去debug。後來在LeetCode上刷題的時候,至少可以看到報錯的測試用例,能看到預期的輸出,這樣思路很快就下來了。有一個同學跟我說,他在LeetCode上做題時,本地測試的過程中,就順便把測試給寫了,自己的測試跑過了再提交,有問題再完善本地測試。如此一個流程下來,不僅加深了對題目的理解,也養成了測試的習慣,思考問題的時候考慮的也會更全面一些(我也想這麼試試)。

測試主要針對的是邏輯,在前端對UI測試個人認為是一件很麻煩的事情。之前見過ThoughtWorks的一個工具,將頁面在各個瀏覽器中截圖,然後進行對比,看看有沒有特別大的問題。雖然也是一種可行的方案,但當頁面中有大量的按鈕可以點,大量的互動操作去處理,截圖來對UI進行測試感覺會比較複雜。

而對邏輯進行測試,工具就相對成熟一些,一般分為以下三類(附上推薦):

對於測試我也是新手,所以推薦阮一峰老師的入門文章:測試框架 Mocha 例項教程。同樣,在很多成熟的Github專案上,你都能看到一個叫test的資料夾,在這裡面可以看到專案開發人員所寫的測試,學習測試的寫法。

工程問題

效能

前端效能問題,很難在寫的時候就全都避免,一般都是在開發完成的測試階段遇到問題後逐步排查的,總會多少經歷一個迭代的過程。

影響前端效能的問題有很多,比如網路速度太慢會影響首屏時間;程式碼的一些寫法也會影響到瀏覽器的渲染;還有一點我覺得很值得注意的就是記憶體洩漏。相關的議題都有很多工具去處理,如果前面Chrome開發者工具部分有好好研究的話,現在對效能問題應該也有一些心得了。

關於載入:

關於渲染:

關於記憶體洩漏:

其他資料推薦:

安全

前端程式碼沒有祕密,畢竟就算混淆也是看的到的。但是,一些安全上的失誤,還是會造成不小的影響。可以看看下面這些事件:

對於安全的具體學習,推薦大家閱讀:

監控

一般來說,測試沒有錯不代表上線沒有錯。尤其是現在可以接入網路的裝置越來越多,加上本來就很多的瀏覽器,測試環境幾乎是不可能完美模擬線上的環境的。因此,對錯誤進行監控就非常重要。

關於前端監控,目前也沒有特別完善的解決方案,給出兩篇文章供大家參考:

業務場景

PC端

傳統的PC端場景,如果不考慮老式瀏覽器的話,其實是很美好的。目前大部分PC端的業務,如果是針對普通使用者的話,一般會相容到IE8。有特殊需要的(如政府網站),會要求相容到IE7(甚至更低)。如果是針對企業使用者或者內部使用者的話,其實就可以開開心心的不考慮相容了。相信很多同學都是從PC端業務開始的,應該都比較熟悉,就不多說了。

為了方便大家的除錯,這裡我分享一下微軟良心出品:

移動端

關於移動端的開發,會涉及很多新的問題,可以先看看下面這篇文章瞭解一下大概的特點:

其實最實用的就是,主要考慮webkit、rem和flex都可以用。這個我認為是和PC端最大的區別。

移動端開發現在也已經有了很長一段時間,也有許多團隊分享了相關的經驗:

移動端和PC另一個很大的不同就是除錯,真機除錯是必不可少的環節,也有許多相關的解決方案:

細分場景

針對終端對業務場景進行分類僅僅是一種方法,其他時候,還有許多細節的場景需要我們去分析,僅就我個人經驗談一下我所知的幾種場景:

純靜態展示頁面

建議使用jQuery(移動端Zepto)進行開發,主要任務是切圖,一般公司首頁這種比較多。

企業後臺

用React做這類專案我認為是非常合適的。元件好分,邏輯清楚,樣式、相容性也不用太在意,主要靠UI框架。

H5動畫(廣告)

有一個H5動畫驚豔了我,讓我見到了這一類專案的潛力。羅斯·決不凋謝,請在移動端(或模擬環境)開啟。

看到這個專案之後,從程式碼註釋中發現了作者並大概看了一下作者的一系列專案,感覺這個方向也是自有一套東西的(對於只關注於業務開發的我,像發現了新大陸一樣)。作者是@shrekshrek,有興趣的同學可以關注一下。

相關文章推薦:

遊戲

對於這個領域,我就更是陌生了。如果有同學願意賜教,感激不盡。

3D場景

WebGL給了瀏覽器3D的能力,Three.js則對相關的API進行了封裝。這相關的業務可能會出現在遊戲中,也可能會出現在一些展示性質的頁面上。不過目前主要的專案中,WebGL相關的技術還沒有大的應用場景。也許將來顯示卡效能和瀏覽器支援水平發展到了足夠的高度,像Unreal一樣的引擎,也許也會出現在瀏覽器之中。

當然實現3D也可能不需要JavaScript參與,CSS 3D現在應用的也很多。常見全景圖展示效果,為了減小複雜度,經常會採用CSS來建立3D場景。

相關資料推薦:

面試

其實我覺得寫這一部分是超出我能力的,畢竟自己沒有什麼經驗,而面試這件事,無論是對面試官還是對應試者其實都是意見相當難的事情。下面所言僅僅是我自己的一些體會,希望拋磚引玉,換來各位前輩多多指教。

面試這件事是圍繞人來的,主要的因素也在人。聽過一句話,大意是:面試就是在尋找將來的同事。我認為,面試就是對自己的表達,需要一種表達的能力在裡面,會表達的人,總是會佔據很大的優勢。

面試是需要準備的,我認為,面試的積累體現在三方面,也是我接下來希望闡述的三方面:

  • 試題的積累
  • 專案的積累
  • 思考的積累

試題的積累

試題的積累是肯定要做的,因為很多時候,在初篩和一面這種基數很大的情況時,直接用題目來篩掉一波人是很有效率的行為。前端的試題,網上能找到很多,有一些很套路,也有一些很個性。不過考察JavaScript,肯定會問一些閉包、this相關的問題;考察CSS,居中的上鏡率就很高;考察相容,肯定離不開各種奇葩瀏覽器的hack。有一些小眾的東西,可能你沒有在專案裡面用過,但是面試官如果問到了,且在常見問題中,那你就吃虧了。所以,準備是肯定要做的。

相關資源推薦:

專案的積累

面試中另一個常見問題就是,你做過什麼專案。我覺得針對這個問題的話,重點要體現這個專案的特點(展示你對需求的理解能力和分析能力)以及你在這個專案中解決了什麼問題(展示你解決問題的能力)。專案應該具有一定的複雜度,如果你在上家公司主要是切圖的話,要麼就談談你對CSS相關的積累,或者直接就談一些自己做的有一定複雜度的專案(還能展示你自學的能力和動力)。按照這個思路來的話,應該問題不大。

思考的積累

我覺得著應該是開發者的一種修養,也是開發者核心價值的一種體現。思考框架背後的東西,思考設計背後的東西,以及,廣泛的閱讀。

相關書籍推薦:

其他資源推薦:

其他

這一部分,會提及一些和前端工作相關的,我認為值得一提的東西。然而畢竟是其他領域的東西,難免會因個人眼界而言辭不當,希望各位前輩多多指教。

提問

一般在技術群裡面,不懂提問浪費時間的人真是太多了。希望能夠靜下心來閱讀張鑫旭的如何提問才能進階成為前端大神?。節省別人的時間也是節省自己的時間。

其實很多時候,大家只要把最小可復現bug的線上demo做出來,說不定就已經不需要提問了。

獲取學習資源

開發人員的時間非常寶貴(因為大家都很忙)。所以,閱讀文章一定要精,多了根本看不過來。

我現在真正還在關注的資源,應該就只有JavaScript Weekly奇舞週刊了。對於我來說,已經足夠了。

資料結構與演算法

對於資料結構與演算法這部分,我曾經專門寫過一篇文章來討論這個問題,歡迎拍磚:

做題推薦:

閱讀推薦:

算導沒有讀過,不過畢竟經典。後面兩本我還沒有讀完,感覺都很不錯。

HTTP

HTTP2的發展可能會為前端帶來很多機會,對這方面感興趣的同學,可以去看看Jerry Qu的小站

相關資料推薦:

後端和資料庫

建議前端開發至少了解一門後端框架,至少了解網站是怎麼回事,有一個整體的把握。推薦一下之前我寫的WEB開發新人指南

我自己的經歷,是先後學習了ThinkPHP和express這兩個後端開發框架,寫了一些簡單的東西。私以為比較重要的點如下:

  • cookie和session
  • 路由控制
  • 許可權控制
  • 如何去建表

Node.js的使用現在也已經是前端的必備技能了(注意是使用)。主要就是使用npm、require的路徑規則、能夠解決報錯資訊這些。

推薦閱讀:

Shell

使用終端也是一項必備技能。首先如果你使用git的話,肯定會用到;此外僅僅善用一些基本技巧,就能大大提高你的開發效率。

使用是最好的學習方法,首先,把Windows棄了吧(或者丟到虛擬機器裡面)。

總結與前瞻

可能以後很多新的東西會進入我們的視野,比如:

Babel等一系列JS的工具,也讓AST(抽象語法樹)進入了前端的視野,並且開始了應用:

WebRTC也已經開始被瀏覽器支援了,即時通訊的開發也許會變的更加簡單。

框架之戰,也沒有出現明顯的勝利者。

等待VR裝置普及起來,我們也許也會在上面寫程式碼?畢竟現在JS跑的地方,已經到嵌入式裝置了。

機會和挑戰是並存的,而新的東西投入應用,也是一個漸進的過程。放眼未來,還要腳踏實地,能夠切實用起來的東西,還是最重要的。

轉自:https://github.com/LeuisKen/leuisken.github.io/issues/3