問題記錄/to do
- 不能連續定義並執行2個匿名函數,也就是說如下的代碼是會報錯的:
(function() {})()
(function() {})()
複製代碼
問題記錄 - 已解決
- es class部分從新學習後 - 實現下繼承/靜態變量等;
- webpack: 用css-loader開啓css-module後,使用mini-css-extract-plugin進行css的split,結果打包出來的文件index.html在瀏覽器中沒有c s s引入的效果?
- for of / for in - 對象的遍歷方法
(function() {
var arr = [1, 2]
Array.prototype.pm = 456;
for (let i in arr) { console.log(`[${i}]: ${arr[i]}`); }
for (let v of arr ) { console.log(`${v}`); }
})()
複製代碼
- 循環引用 - 模型是怎樣的 圖??
var a = { b: 1 };
a.b = a;
console.log(a);
複製代碼
- 解決方法:咱們在深拷貝中若是碰見了循環引用而未做專門的處理,就會無限遞歸形成內存溢出,那麼處理的思路呢?應該是:
- 利用緩存的思想,用一個數組緩存已經遍歷過的引用,每次引用時只要查找緩存中是否登記過;若是已經登記過,則就不須要再遞歸了;
- 循環引用 屢次引用的地址歸爲一個便可,不須要遞歸挖掘:由於對於循環引用的處理就是:避免遞歸,只在第一次遞歸引用,後面就再也不遞歸了
感慨&頓悟
- 有時候感受,之因此能複用,就是由於有名字啊:命名其實對不少事物發展頗有幫助
關於學習方法
關於讀書
- 應該要對知識點以Blog的形式進行輸出,尤爲是經典知識點
- 也就是反饋式學習,有沒有讀者沒關係,必定要儘量輸出
- 那些手冊中能查到的,或者記憶性的,就不要複述了,API隨時會變,要去深刻理解背後的設計機制,實現原理這樣子的東西
- 以不變應萬變,重視原理,要否則只會疲於奔命
- 關於閱讀,有時候能夠出小聲讀能夠有助於咱們集中注意力,效果會好一些
關於算法
- 學習算法的本質是什麼??是一種訓練。
- 設計一個好的數據結構,再加一些算法,就行了
- 因此任何算法,都應先設計好數據結構(數據結構咱們能夠從基礎/元數據結構加工/改造/組合而來),讓數據結構自己描述問題模型,而後再組合使用相應的算法或者設計更優的算法(若是寫算法,連咱們要操做怎樣的數據都不清楚的話,算法從何談起);
- 好的算法和好的軟件同樣,是迭代而來的;
- 必定要學會思考,去分析問題+條件+目的,而後嘗試給出一步接一步的方案
- 另外,不要思考不通就一會兒把答案看完,能夠看一部分,提示性的,剩下的本身繼續思考,最後再對比本身的方案和主流方案,有利於彌補思惟缺陷和提醒思惟定勢
- 再到後面效率越高的排序,要有「輔助函數」的意識
-
遞歸
- 遞歸終止條件 - 就是在知足某一條件的狀況下 再也不調用自身 而是返回一個‘正常值’(個人理解就是:可用於計算的值)
- 遞歸的本質是什麼??就是棧,遞歸的過程就是入棧(父函數到子函數) -> 出棧執行(子函數返回值到父函數),每一次出棧執行,咱們都把結果用臨時變量記錄做爲棧中下一個要出棧執行的函數的參數;
關於設計模式
訂閱模式
- 事件隊列,只是訂閱模式的一種應用;
- 訂閱的本質:就是把給定的一個回調添加到某一頻道的隊列中去;後面的觸發以及管理,都經過該頻道;
前端js手寫
- 節流和防抖的應用場景區別
- 防抖和節流都是限制某一時間段代碼執行的頻次,可是實現原理不太同樣
- 防抖,能夠保證在delay內不會執行2次代碼,也就是某一段時間內只執行一次,並且是最後一次的代碼會被執行;節流,保證在一個時間間隔內只執行一次代碼,並且是該段間隔中的第一次的代碼;
-
防抖適用場景:
- 提交,只提交最後一次;
- 輸入框聯想,避免頻繁聯想,而是在停頓輸入後一個delay內去請求聯想;
- 例如:你正在適用掘金的編輯器,在你輸入後的一個delay內,會右上角會顯示自動保存爲草稿,這裏必然用的是防抖,不然頻繁請求,會讓服務器的壓力很大;
-
節流適用場景:
- resize、動畫、滑動條事件(me:由於是間隔執行,就能夠認爲是‘均勻’的,對於動畫等同時強調流暢性的場景)
- 深克隆
關於原理
js原理
關於源碼閱讀
// 特殊值校驗
// 主體程序
// 輔助函數
// 返回值
複製代碼
style
CSS
- 利用了block水平元素寬度能夠隨父容器調節流動的特性
- 參考
- BFC特性
- 包裹浮動元素
- 解決margin疊加
- BFC啓用
- overflow 設置爲非visible的值
- position:absolute / fixed
- display: flow-root(支持有限)
- 建立table-cell表格相關
- column-span:all 建立多列布局
Flex
- 定義爲Flex佈局的元素若是不給明確尺寸,會自動伸展到和容器同一寬度
SCSS/SASS
HTTP
http 鑑權
- 401 是用戶身份認證:是否爲經過認證的用戶
- 403 是當前用戶權限認證:當前用戶是否擁有某權限
緩存
- 緩存在網絡結構中,是一個節點,就相似於代理那樣(固然,瀏覽器也能夠具備緩存能力,至關於給本身的通訊增設了一個緩存節點);
- 相比於代理,緩存具備將服務器端資源緩存到本身本地的能力,並經過一系列Http指令/機制(例如「新鮮度檢測」)來肯定是否給客戶端提供本地的緩存資源;
- 本質上是一種網絡效率/資源優化機制;
- 緩存的核心:新鮮度校驗;
- 新鮮度校驗通常基於兩種機制:
- 緩存資源的時間屬性(上次修改時間等)
- Expires
- cache-control: Max-Age
- 緩存資源自己實體的屬性(ETag(Entity Tag)等)
- 新鮮度校驗通常發生在緩存節點和服務器節點之間,通訊使用的是http 1.0 和 http 1.1爲緩存提供的一些首部屬性;
- 緩存的控制:主要由服務端(開發者能夠經過服務器配置文件)控制,固然瀏覽器也能夠經過一些操做(Refresh)去發送一些帶有cache-control的請求指令,另外文檔自己也能夠設置一些緩存指令:例如在html文檔中,HTTP 2.0 提供的來分配http首部信息(可是這個方案性能和支持度都很差,不建議使用)
- 瀏覽器緩存:實際上是瀏覽器自己扮演了一個緩存節點來提供自身和服務器之間的緩存服務;
- 緩存:緩存資源 + 緩存標識
- 咱們能夠將多個緩存指令配合使用
- 瀏覽器緩存策略:
- 強緩存
- Expires
- HTTP 1.0
- 一種兼容寫法,自己是被淘汰的機制;
- 優先級低
- Cache-Control
- HTTP 1.1
- 響應頭 + 請求頭 均可以用
- 優先級高
- 協商緩存
- last-Modified
- 響應頭: Last-Modified
- 請求頭: If-Modified-Since
- 優先級低
- 弊端
- ETag
- 響應頭: ETag
- 請求頭: If-None-Match
- 優先級高
- 瀏覽器2種緩存策略比較:
- 性能:強緩存好
- 精確度: 協商緩存高
- 優先級: 協商緩存高
- 另外:強緩存由服務器經過強緩存指令對緩存進行設置,因此是一個單向的,協商緩存則是由一組:響應頭指令 + 請求頭指令 配合使用的;
- 關於瀏覽器緩存
跨域
jsonp
- jsonp的原理就是向後臺經過url參數(通常約定爲callback)傳遞一個回調函數的句柄(函數名),後臺在經過請求信息(參數)計算處理後在響應中傳回一個拼接的js(callback(data))
React
關於React的diff算法
- diff的概念:比對兩棵樹以比較有效率實現ui同步。
-
算法實現
- 原來的算法爲對樹(render方法會生成由React自定義數據結構(核心屬性有type,props,children)的virtrualDomTree)的遞歸比較,一層一層比較,先比較父節點,再比較子節點。
- 在每一層中的比較中,對於當前比較節點,按類型分爲:React元素或者原生DOM節點
- 對於Dom節點比較,先比較類型type:
- type不同,則直接從該節點爲頂點銷燬子樹(並銷燬其狀態),而後用新生成VirtrualDomTree替換這一部分;
- 若是type一致,則比較其props/屬性,只更舊樹上的變化的屬性;
- 對於React元素的比較:也是先比較type,
- type不一致的和Dom節點的處理同樣,也是子該節點如下銷燬舊樹,把新樹替換上去;
- type一致的,保留舊virtrualDomTree的實例,而後先把新樹的props經過比對更新到舊樹上,而後對新舊兩個樹的children列表進行比對(這裏就是有無key的影響體現了,當子節點列表有差別時,會比對產生一個mutation),而後遞歸去render children(子節點)這一層,diff規則和上一層,同樣;
- 那麼,基於以上,咱們就能夠理解當列表中兩個元素相互交換位置時會發生什麼??key在算法中發揮做用主要是當前層/節點的children若是是列表的話,須要首先對這個列表過一遍,以保證列表的增刪改/次序位置/同節點屬性等保持一致:
- 這個固然要分有無key的狀況來討論
- 有key的狀況下,就會用key來進行當前節點惟一性的標記,在列表比對時,用key來表明節點進行children的列表比對,key相同的保持舊節點實例不變,只比對變動屬性
- 無key的狀況下,就是普通節點按次序比較了,例如2個節點僅僅是調換了一下位置就可能會把舊節點銷燬了
- 另外關於index不適合做key的狀況爲何(其實key本質上是列表節點的一種身份標記,能夠告訴react的diff算法,用來標誌新舊兩棵樹上同一個列表節點,經過比對key,用key能夠區分,那些是舊樹就有的節點,哪些是新樹新增長或者刪除的節點,key相同的狀況下,首先是保留舊節點實例的
- key的來源(原則:保持列表內惟一便可)
- 來自模型(通常源於數據庫)的id值
- 能夠用值的一部分利用hash映射算法生成,固然hash 要足夠優
- 在不牽扯順序調整的狀況下,數組index也能夠勝任
- 對了,說到對惟一性的標識,怎麼能少了es6的symbol呢
React-router
React 小細節
- 剛用react那會兒對es6也不算熟,當時就感受,爲何
<Todo onClick={(e) => onClick(e)} />
// 在不指定傳參的狀況 與下面語句基本相等 ??
<Todo onClick={onClick} />
複製代碼
今天盯着看了會兒,這不就是一個函數表達式嗎??眼拙啊css
onClick={(e) => onClick(e)}
// 等價於
onClick={function() { return onClick(e)}}
複製代碼
Redux
- 關於react + redux中組件的劃分:儘可能把視圖和容器分開來設計組件,之間能夠經過props來傳遞信息:
- 容器組件,凡是直接與Redux的store打交道的都是容器組件,通常都是通過HOC connect包裝後的組件
- 展現組件,純展現性的組件了,通常就是函數組件
- 在面對具體業務時,思路:
- 咱們的首要任務是根據任務模型設計state模型,就是設計reducer,最好的方法就是咱們先寫一個defaultState做爲默認值,也會對該view/功能對應的state又一個比較直觀的認識;
- 而後思考咱們須要哪些操做(action.type),固然這些共用型的常量確定要用大寫的const常量,而且在一個文件中集中配置管理
- 而後就是設計action了
- 最後把咱們的reducer 經過combineReducers來組合起來,而後交給createStore便可;
- 而後,進入咱們業務設計部分,這部分就分爲容器組件和展現組件的劃分了
- 考慮:數據的交互實際上是用戶和view都和store進行交互,讀寫數據,這是設計的一個思考前提,也就是咱們要了解這一功能,數據須要從哪裏來,到哪裏去,觸發什麼;
- 話說,Redux完成一個功能所須要的模版文件太多了,並且不直觀,業界有mobx這樣的替代解決方案,但也有其一點點侷限性,嗯嗯,給Redux作個輔助庫,這一塊找時間值得思考嘗試下
使用
- Switch會只渲染第一個path屬性和loaction匹配的
React-router 源碼閱讀感悟
- Just Component(一切皆組件)
- 組件封裝了path和component之間的映射關係,而path,是標準URL中的一部分;
- 傳遞給組件的props.history.action屬性,用法舉例:
- 翻頁動畫:咱們能夠根據action的值來判斷是POP 或 PUSH 從而採起不通的翻頁動畫
Vue
關於組件化的認識(摘自Vue官網)
一個重要的事情值得注意,關注點分離不等於文件類型分離。在現代 UI
開發中,咱們已經發現相比於把代碼庫分離成三個大的層次並將其相互交織起來,
把它們劃分爲鬆散耦合的組件再將其組合起來更合理一些。
在一個組件裏,其模板、邏輯和樣式是內部耦合的,
而且把他們搭配在一塊兒實際上使得組件更加內聚且更可維護。
複製代碼
Vue組件
- Vue組件本質上是一個有名稱的Vue實例,特色是能夠經過名稱進行復用
- 任何Vue應用,都有一個根實例、
H5 app
- 高清圖顯示方案
- 提供高清圖:位圖像素得和物理像素的數量一致,那麼,當dp r=2時,css像素(200 * 300)的img,其實是由(400 * 600)的設備像素提供的顯示的,那麼,基於位圖像素和物理像素數量一致纔不會發生就近取色的算法(會致使模糊),因此,咱們要針對dpr = 2 && css(200 * 300)的img 提供(400*600)的高清圖
- dpr的獲取:
window.devicePixelRatio
複製代碼
@media (-webkit-device-pixel-ratio){}
@media (-webkit-min-device-pixel-ratio){}
@media (-webkit-max-device-pixel-ratio){}
複製代碼
koa中間件編寫感悟
- 中間件 本質就是一個能夠生成(返回)async函數的工廠
- 每一箇中間件均可以拿到ctx和next由koa傳入的參數,剩餘的參數咱們經過工廠傳入,也就是在app.use註冊時傳入
- 中間件要考慮next調用的時機,另外,若是要進行respoons的相關回復,咱們要考慮header和body兩部分的設置
- 注意容錯
- 對於某些中間件中依賴的部分非核心很是用庫,咱們能夠經過語義等將其看成黑盒對待,重視其輸入和輸出以及做用
- 核心庫koa-send
- 最核心的實現就是:
ctx.body = fs.createReadStream(path)
- 當咱們須要獲取file時,node提供的fs和path配合使用,威力很強
koa-views
koa-router
- Nesting routers is supported; - 支持路由嵌套
forums.use('/forums/:fid/posts', posts.routes(),posts.allowedMethods());
複製代碼
工程化
webpack
- 關於module、chunk和bundle的區別
- module
- module對應的是咱們的源碼文件,通常和源碼文件一一對應,也是webpack的輸入
- chunk
- chunk是webpack按照配置的規則對module進行拆分合並後的東西,通常和module是一對多(也能夠是一對一,看具體的split設置)的關係,咱們的codeSplit規則通常就做用於module到chunk這個過程
- bundle
- bundle是webpack對chunk進行處理(編譯壓縮等)後輸出到dist的文件(就是咱們最終打包產生的文件),通常和chunk是一一對應的關係;
- css split:在css文件比較大時,能夠分離打包css,把css打包爲單獨的文件(能夠避免將css打包到js中,增大js的體積),而後加快加載速度(css是與DOM並行加載的,js默認則是阻塞式加載)
- 任什麼時候候使用第三方庫時,閱讀文檔都是第一步驟:在提取並分離文件的extract-text-webpack-plugin主頁咱們就看到提醒,webpack v4以後咱們提取分離文件應該用mini-css-extract-plugin
babel
- 在webpack中配置babel時,babel-loader會讀取.babelrc配置文件
HMR
- 不使用react-hot-loader的話,咱們改變React組件內容,瀏覽器那邊是自動刷新,而不是無刷新的HMR
fetch
- 從MDN關於Body對象的描述,咱們能夠知道爲何fetch在獲取到數據後,中間還得有一層返回Body對象方法的then:
fetch('http://example.com/movies.json')
.then(function(response) {
// 爲何後面能夠接then ?
// 由於Body對象的方法(這裏是response.json)返回的是一個Promise對象
return response.json();
})
.then(function(myJson) {
// 這裏的then是上面response.json()返回的
console.log(myJson);
});
複製代碼
優化
關於優化,能夠分爲用戶體驗優化(例如Loading和skeleton), 和性能優化,例如縮短首屏加載時間(理念通常是:經過codeSplit 和 緩存機制配合,讓那些不易變更的包儘可能利用長緩存機制,減小遠程資源請求次數(打包出來的index.html中的bundle.js在沒有緩存的狀況下,都會阻塞式地遠程下載)。縮小首屏加載包的體積:壓縮,路由和組件級的codeSplit,儘可能減小加載沒必要要加載的代碼。這些實現通常依靠在webpack中配置以及各類懶加載組件等輔助實現)html
性能優化
「咱們應該忘記忽略很小的性能優化,
能夠說在97%的狀況下,過早的優化是萬惡之源,
而咱們應該關心對性能影響最關鍵的那另外3%的代碼」 -- 高德納
複製代碼
也就是說:不要將優化性能的精力浪費在對總體性能影響不大的代碼上,而對於性能有關鍵影響的部分,優化並不嫌早。前端
性能優化梳理
白屏 {
loading
== 僞服務端渲染(只渲染首屏,poppeteer)
cache + splitCode:= 變化部分 + 不易變化部分(適合做爲長期緩存,
通常爲公共依賴之類的)
開啓Http2
}
從白屏 到 FMP {
sketon(代替無心義頁面)
}
從FMP到TTI(這一階段主要是js阻塞:js體積 + js自己執行速度) {
TreeShaking
pollyfill動態加載
動態加載es6
路由級別split code:將首屏js拆解出來
}
組件加載 {
codeSplit - 主要依賴於懶加載
預加載 - 原理:hover
keep-alive:react-keep-alive
}
複製代碼
加載優化
首屏加載
執行優化
場景問題解決
大數據量list渲染問題
- 分爲「有分頁」和「無分頁」兩種方案
- 「有分頁」:除了前端分頁器實現,還有就是(移動端用的多)下拉到底部時觸發請求,得到分頁後的數據
- 「無分頁」:就須要用到「虛擬列表」的技術了
版本控制 git
- git的版本控制:本地倉庫和遠程倉庫配合使用,並且就存儲機制和內容方面,基本一致,也就是git一視同仁;
- git只制定了靈活度很高的規則,至於怎麼玩,就由你們去想象了
- 分佈式系統,也就是基本每個節點,均可以做爲另外一個節點的服務器/代碼倉庫,資源/代碼都是管理在每個節點上的;