一個前端基礎需要掌握的 28 個 JavaScript 技巧(第二章)

不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發工作,我們經常會遇到這樣的情況:給定的幾行代碼,我們需要知道其輸出內容和順序。因為javascript是一門單線程語言,所以我們可以得出結論:

各位小伙伴在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于HTML/CSS/javaScript/Vue等多個知識點高級進階干貨需要的可以免費分享給大家,有需要者請進群點擊進入1045267283

一個前端基礎需要掌握的 28 個 JavaScript 技巧(第一章)

14. 實現函數 bind 方法

實現函數的 bind 方法核心是利用 call 綁定 this 指向,同時考慮了一些其他情況,例如

bind 返回的函數被 new 調用作為構造函數時,綁定的值會失效并且改為 new 指定的對象

定義了綁定后函數的 length 屬性和 name 屬性(不可枚舉屬性)

綁定后函數的 prototype 需指向原函數的 prototype(真實情況中綁定后的函數是沒有 prototype 的,取而代之在綁定后的函數中有個 內部屬性 [[TargetFunction]] 保存原函數,當將綁定后函數作為構造函數時,將創建的實例的 __proto__ 指向 [[TargetFunction]] 的 prototype,這里無法模擬內部屬性,所以直接聲明了一個 prototype 屬性)

15. 實現函數 call 方法

原理就是將函數作為傳入的上下文參數(context)的屬性執行,這里為了防止屬性沖突使用了 ES6 的 Symbol 類型

16. 簡易的 CO 模塊

使用方法:

run 函數接受一個生成器函數,每當 run 函數包裹的生成器函數遇到 yield 關鍵字就會停止,當 yield 后面的 promise 被解析成功后會自動調用 next 方法執行到下個 yield 關鍵字處,最終就會形成每當一個 promise 被解析成功就會解析下個 promise,當全部解析成功后打印所有解析的結果,衍變為現在用的最多的 async/await 語法

17. 函數防抖

leading 為是否在進入時立即執行一次,原理是利用定時器,如果在規定時間內再次觸發事件會將上次的定時器清除,即不會執行函數并重新設置一個新的定時器,直到超過規定時間自動觸發定時器中的函數

同時通過閉包向外暴露了一個 cancel 函數,使得外部能直接清除內部的計數器

18. 函數節流

和函數防抖類似,區別在于內部額外使用了時間戳作為判斷,在一段時間內沒有觸發事件才允許下次事件觸發,同時新增了 trailing 選項,表示是否在最后額外觸發一次

19. 圖片懶加載

getBoundClientRect 的實現方式,監聽 scroll 事件(建議給監聽事件添加節流),圖片加載完會從 img 標簽組成的 DOM 列表中刪除,最后所有的圖片加載完畢后需要解綁監聽事件

intersectionObserver 的實現方式,實例化一個 IntersectionObserver ,并使其觀察所有 img 標簽

當 img 標簽進入可視區域時會執行實例化時的回調,同時給回調傳入一個 entries 參數,保存著實例觀察的所有元素的一些狀態,比如每個元素的邊界信息,當前元素對應的 DOM 節點,當前元素進入可視區域的比率,每當一個元素進入可視區域,將真正的圖片賦值給當前 img 標簽,同時解除對其的觀察

20. new 關鍵字

21. 實現 Object.assign

22. instanceof

原理是遞歸遍歷 right 參數的原型鏈,每次和 left 參數作比較,遍歷到原型鏈終點時則返回 false,找到則返回 true

23. 私有變量的實現

使用 Proxy 代理所有含有?_?開頭的變量,使其不可被外部訪問

通過閉包的形式保存私有變量,缺點在于類的所有實例訪問的都是同一個私有變量

另一種閉包的實現,解決了上面那種閉包的缺點,每個實例都有各自的私有變量,缺點是舍棄了 class 語法的簡潔性,將所有的特權方法(訪問私有變量的方法)都保存在構造函數中

通過 WeakMap 和閉包,在每次實例化時保存當前實例和所有私有變量組成的對象,外部無法訪問閉包中的 WeakMap,使用 WeakMap 好處在于當沒有變量引用到某個實例時,會自動釋放這個實例保存的私有變量,減少內存溢出的問題

24. 洗牌算法

早前的 chrome 對于元素小于 10 的數組會采用插入排序,這會導致對數組進行的亂序并不是真正的亂序,即使最新的版本 chrome 采用了原地算法使得排序變成了一個穩定的算法,對于亂序的問題仍沒有解決

通過洗牌算法可以達到真正的亂序,洗牌算法分為原地和非原地,圖一是原地的洗牌算法,不需要聲明額外的數組從而更加節約內存占用率,原理是依次遍歷數組的元素,將當前元素和之后的所有元素中隨機選取一個,進行交換

25. 單例模式

通過 ES6 的 Proxy 攔截構造函數的執行方法來實現的單例模式

26. promisify

使用方法:

promisify 函數是將回調函數變為 promise 的輔助函數,適合 error-first 風格(nodejs)的回調函數,原理是給 error-first 風格的回調無論成功或者失敗,在執行完畢后都會執行最后一個回調函數,我們需要做的就是讓這個回調函數控制 promise 的狀態即可

這里還用了 Proxy 代理了整個 fs 模塊,攔截 get 方法,使得不需要手動給 fs 模塊所有的方法都包裹一層 promisify 函數,更加的靈活

27. 優雅的處理 async/await

使用方法:

無需每次使用 async/await 都包裹一層 try/catch ,更加的優雅,這里提供另外一個思路,如果使用了 webpack 可以編寫一個 loader,分析 AST 語法樹,遇到 await 語法,自動注入 try/catch,這樣連輔助函數都不需要使用

28. 發布訂閱 EventEmitter

通過 on 方法注冊事件,trigger 方法觸發事件,來達到事件之間的松散解耦,并且額外添加了 once 和 off 輔助函數用于注冊只觸發一次的事件以及注銷事件

29. 實現 JSON.stringify(附加)

使用 JSON.stringify 將對象轉為 JSON 字符串時,一些非法的數據類型會失真,主要表現如下

如果對象含有 toJSON 方法會調用 toJSON

在數組中

存在 Undefined/Symbol/Function 數據類型時會變為 null

存在 Infinity/NaN 也會變成 null

在對象中

屬性值為 Undefined/Symbol/Function 數據類型時,屬性和值都不會轉為字符串

屬性值為 Infinity/NaN ,屬性值會變為 null

日期數據類型的值會調用 toISOString

非數組/對象/函數/日期的復雜數據類型會變成一個空對象

循環引用會拋出錯誤

相關CSS知識點:這一次讓你徹底弄懂 JavaScript 執行機制

在此小編再次感謝大家對我的支持,需要更多相關資料,視頻請加群點擊進入1045267283

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容