<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端進階必會的22個JavaScript技巧總結(jié)

          共 3796字,需瀏覽 8分鐘

           ·

          2021-05-18 08:30

          前言

          關(guān)于技術(shù),只有不停重復學習,方能如扎如穩(wěn)的前行。

          1.函數(shù)柯里化

          函數(shù)柯里化的是一個為多參函數(shù)實現(xiàn)遞歸降解的方式。其實現(xiàn)的核心是:

          1. 要思考如何緩存每一次傳入的參數(shù)

          2. 傳入的參數(shù)和目標函數(shù)的入?yún)⒆霰容^

          這里通過閉包的方式緩存參數(shù),實現(xiàn)如下:

          使用方式如下:

          函數(shù)柯里化僅僅只是上面求和的這種運用嗎??

          ??這個問題,有必要去??一下。其實利用函數(shù)柯里化這種思想,我們可以更好的實現(xiàn)函數(shù)的封裝。

          就比如有監(jiān)聽某一事件那么就會有移除該事件的操作,那么就可以利用柯里化的思想去封裝代碼了。

          或者說一個輸入 A 有唯一并且對應的輸出 B,那么從更大的角度去思想這樣的工程項目是更安全,獨立的。也便于去維護。

          2.關(guān)于數(shù)組

          手寫 map 方法

          map() 方法根據(jù)回調(diào)函數(shù)映射一個新數(shù)組

          手寫 filter 方法

          filter() 方法返回一個數(shù)組,返回的每一項是在回調(diào)函數(shù)中執(zhí)行結(jié)果 true。

          filter 和 map 的區(qū)別:filter 是映射出條件為 true 的 item,map 是映射每一個 item。

          手寫 reduce 方法

          reduce() 方法循環(huán)迭代,回調(diào)函數(shù)的結(jié)果都會作為下一次的形參的第一個參數(shù)。

          手寫 every 方法

          every() 方法測試一個數(shù)組內(nèi)的所有元素是否都能通過某個指定函數(shù)的測試。它返回一個布爾值。

          手寫 some 方法

          some() 方法測試數(shù)組中是不是至少有 1 個元素通過了被提供的函數(shù)測試。它返回的是一個 Boolean 類型的值。

          手寫 find 方法

          find() 方法返回數(shù)組中滿足提供的測試函數(shù)的第一個元素的值。否則返回 undefined。

          拉平數(shù)組

          將嵌套的數(shù)組扁平化,在處理業(yè)務數(shù)據(jù)場景中是頻率出現(xiàn)比較高的。那如何實現(xiàn)呢?

          • 利用 ES6 語法 flat(num) 方法將數(shù)組拉平。

          該方法不傳參數(shù)默認只會拉平一層,如果想拉平多層嵌套的數(shù)組,需要傳入一個整數(shù),表示要拉平的層級。該返回返回一個新的數(shù)組,對原數(shù)組沒有影響。

          • 利用 reduce() 方法將數(shù)組拉平。

          利用 reduce 進行迭代,核心的思想是遞歸實現(xiàn)。

          • 模擬棧實現(xiàn)數(shù)組拉平

          該方法是模擬棧,在性能上相對最優(yōu)解。

          3.圖片懶加載 & 惰性函數(shù)

          實現(xiàn)圖片懶加載其核心的思想就是將 img 的 src 屬性先使用一張本地占位符,或者為空。然后真實的圖片路徑再定義一個 data-set 屬性存起來,待達到一定條件的時將 data-img 的屬性值賦給 src。

          如下是通過scroll滾動事件監(jiān)聽來實現(xiàn)的圖片懶加載,當圖片都加載完畢移除事件監(jiān)聽,并且將移除 html 標簽。

          scroll滾動事件容易造成性能問題。那可以通過 IntersectionObserver 自動觀察 img 標簽是否進入可視區(qū)域。

          實例化 IntersectionObserver 實例,接受兩個參數(shù):callback 是可見性變化時的回調(diào)函數(shù),option 是配置對象(該參數(shù)可選)。

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

          如上是懶加載圖片的實現(xiàn)方式。

          值得思考的是,懶加載和惰性函數(shù)有什么不一樣嘛?

          我所理解的懶加載顧名思義就是需要了才去加載,懶加載正是惰性的一種,但惰性函數(shù)不僅僅是懶加載,它還可以包含另外一種方向。

          惰性函數(shù)的另一種方向是在重寫函數(shù),每一次調(diào)用函數(shù)的時候無需在做一些條件的判斷,判斷條件在初始化的時候執(zhí)行一次就好了,即下次在同樣的條件語句不需要再次判斷了,比如在事件監(jiān)聽上的兼容。

          4.預加載

          預加載顧名思義就是提前加載,比如提前加載圖片。

          當用戶需要查看時,可直接從本地緩存中取。預加載的優(yōu)點在于如果一張圖片過大,那么請求加載圖片一定會慢,頁面會出現(xiàn)空白的現(xiàn)象,用戶體驗感就變差了,為了提高用戶體驗,先提前加載圖片到本地緩存,當用戶一打開頁面時就會看到圖片。

          5.節(jié)流 & 防抖

          針對高頻的觸發(fā)的函數(shù),我們一般都會思考通過節(jié)流或者防抖去實現(xiàn)性能上的優(yōu)化。

          節(jié)流實現(xiàn)原理是通過定時器以和時間差做判斷。定時器有延遲的能力,事件一開始不會立即執(zhí)行,事件結(jié)束后還會再執(zhí)行一次;而時間差事件一開始就立即執(zhí)行,時間結(jié)束之后也會立即停止。

          結(jié)合兩者的特性封裝節(jié)流函數(shù):

          函數(shù)節(jié)流不管事件觸發(fā)有多頻繁,都會保證在規(guī)定時間內(nèi)一定會執(zhí)行一次真正的事件處理函數(shù)。

          防抖實現(xiàn)原理是通過定時器,如果在規(guī)定時間內(nèi)再次觸發(fā)事件會將上次的定時器清除,即不會執(zhí)行函數(shù)并重新設置一個新的定時器,直到超過規(guī)定時間自動觸發(fā)定時器中的函數(shù)。

          6.實現(xiàn) new 關(guān)鍵字

          7.實現(xiàn) instanceof

          instanceof 運算符用于檢測構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在某個實例對象的原型鏈上。

          8.實現(xiàn) call,apply,bind

          • call

          call 函數(shù)實現(xiàn)的原理是借用方法,關(guān)鍵在于隱式改變this的指向。

          • apply

          apply 函數(shù)實現(xiàn)的原理和 call 是相同的,關(guān)鍵在于參數(shù)的處理和判斷。

          call() 方法的作用和 apply() 方法類似,區(qū)別就是 call() 方法接受的是參數(shù)列表,而 apply() 方法接受的是一個參數(shù)數(shù)組。

          • bind

          bind() 方法創(chuàng)建一個新的函數(shù),在 bind() 被調(diào)用時,這個新函數(shù)的 this 被指定為 bind() 的第一個參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時使用。

          實現(xiàn)的關(guān)鍵思路:

          1. 拷貝保存原函數(shù),新函數(shù)和原函數(shù)原型鏈接

          2. 生成新的函數(shù),在新函數(shù)里調(diào)用原函數(shù)

          9.封裝數(shù)據(jù)類型函數(shù)

          10.自記憶函數(shù)

          11.是否存在循環(huán)引用

          12.拷貝函數(shù)

          拷貝數(shù)據(jù)一直是業(yè)務開發(fā)中繞不開的技巧,對于深淺拷貝數(shù)據(jù)之前寫過一篇文章來講述聊聊深拷貝淺拷貝。

          • 通過深度優(yōu)先思維拷貝數(shù)據(jù)(DFS)

          深度優(yōu)先是通過縱向的維度去思考問題,在處理過程中也考慮到對象環(huán)的問題。

          解決對象環(huán)的核心思路是先存再拷貝。一開始先通過一個容器用來儲存原來的對象再進行拷貝,在每一次拷貝之前去查找容器里是否已存在該對象。這樣就切斷了原來的對象和拷貝對象的聯(lián)系。

          • 通過廣度優(yōu)先思維拷貝數(shù)據(jù)(BFS)

          廣度優(yōu)先是通過橫向的維度去思考問題,通過創(chuàng)造源隊列和拷貝數(shù)組隊列之間的關(guān)系實現(xiàn)拷貝。

          13.Promise 系列

          之前寫過一篇關(guān)于 Promise 的學習分享。

          Promsie.all

          Promsie.race

          Promsie.finally

          14.實現(xiàn) async-await

          15.實現(xiàn)簡易訂閱 - 發(fā)布

          16.單例模式

          單例模式:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。實現(xiàn)方法一般是先判斷實例是否存在,如果存在直接返回,如果不存在就先創(chuàng)建再返回。

          17.實現(xiàn) Object.create

          Object.create() 方法創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__。

          該方法是實現(xiàn)了已有對象和新建對象的原型是一個淺拷貝的過程。

          18.實現(xiàn) ES6 的 class 語法

          使用 Object.create() 方法將子類的實例對象繼承與父類的原型對象,通過 Object.setPrototypeOf() 能夠?qū)崿F(xiàn)從父類中繼承靜態(tài)方法和靜態(tài)屬性。

          19.實現(xiàn)一個 compose 函數(shù)

          compose 函數(shù)是用來組合合并函數(shù),最后輸出值的思想。在 redux 源碼中用于中間件的處理。

          • 使用 while 循環(huán)實現(xiàn)
          • 使用 reduce 迭代實現(xiàn)

          20.實現(xiàn)異步并行函數(shù)

          fn 是一個返回 Promise 的函數(shù)才可使用下面的函數(shù):

          fn 不是一個返回 Promsie 的話那就包一層:

          21.實現(xiàn)異步串行函數(shù)

          22.私有變量的實現(xiàn)

          以上是 es5 實現(xiàn)的私有變量的封裝,通過使用 WeakMap 可以擴展每個實例所對應的私有屬性,私有屬性在外部無法被訪問,而且隨 this 對象的銷毀和消失。

          這里有個小細節(jié)值得一提, 請看如下的代碼:

          如上是掛在到原型上的方法和每個實例獨有的方法不同寫法。它們有什么區(qū)別呢?(ps: 可以手動打印)

          調(diào)用原型上的方法那么私有變量的值是與最近一個實例調(diào)用原型方法的值。其上一個實例的值也是隨之改變的,那么就出現(xiàn)問題了...

          而使用 WeakMap 可以解決如上的問題:做到將方法掛在到原型,且不同時期同一個實例調(diào)用所產(chǎn)生的結(jié)果是一致的。

          源代碼

          javascript--,歡迎 star

          總結(jié)

          我一直認為有輸入就得有輸出,那總結(jié)就是最好的輸出方式了。因此有了一篇這樣的文章,希望讀者能靜下來去手寫并理解 code 的思路和運行過程,我想也會對 js 有更深入的理解。(ps: 可以一起探討)

          如上的總結(jié),如有新的內(nèi)容也會持續(xù)更新...

          參考資料

          一個合格的中級前端工程師需要掌握的 28 個 JavaScript 技巧

          MDN

          更多優(yōu)質(zhì)原創(chuàng)內(nèi)容請點擊“閱讀原文”了解~


          關(guān)注公眾號后可以加入前端技術(shù)社群哦~

          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人99大香蕉 | 亚洲男人天堂一本 | 国产做爱视频网站18 | 久久国产成人精品Av | 三级视频在线看 |