<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>

          code-review之前端代碼優(yōu)化匯總

          共 2975字,需瀏覽 6分鐘

           ·

          2021-11-13 00:58

          所謂無(wú)規(guī)矩不成方圓,前端時(shí)間在團(tuán)隊(duì) code-review 中發(fā)現(xiàn),鬼哥?推薦大家可以大致過(guò)一遍,形成自己的編碼習(xí)慣

          本文主要針對(duì)一些 JavaScript 進(jìn)行優(yōu)化,使之更加健壯,可讀性更強(qiáng),更以維護(hù)。

          if 判斷的優(yōu)化

          1、最簡(jiǎn)單的方法:if 判斷

          let?commodity?=?{
          ??phone:?'手機(jī)',
          ??computer:?'電腦',
          ??television:?'電視',
          ??gameBoy:?'游戲機(jī)',
          }

          function?price(name)?{
          ??if?(name?===?commodity.phone)?{
          ????console.log(1999)
          ??}?else?if?(name?===?commodity.computer)?{
          ????console.log(9999)
          ??}?else?if?(name?===?commodity.television)?{
          ????console.log(2999)
          ??}?else?if?(name?===?commodity.gameBoy)?{
          ????console.log(3999)
          ??}
          }
          price('手機(jī)')?//?9999

          缺點(diǎn):代碼太長(zhǎng)了,維護(hù)和閱讀都很不友好

          2、好一點(diǎn)的方法:Switch

          let?commodity?=?{
          ??phone:?'手機(jī)',
          ??computer:?'電腦',
          ??television:?'電視',
          ??gameBoy:?'游戲機(jī)',
          }
          const?price?=?(name)?=>?{
          ??switch?(name)?{
          ????case?commodity.phone:
          ??????console.log(1999)
          ??????break
          ????case?commodity.computer:
          ??????console.log(9999)
          ??????break
          ????case?commodity.television:
          ??????console.log(2999)
          ??????break
          ????case?commodity.gameBoy:
          ??????console.log(3999)
          ??????break
          ??}
          }
          price('手機(jī)')?//?9999

          3、更優(yōu)的方法: 策略模式

          策略模式利用組合、委托和多態(tài)等技術(shù)和思想,可以有效地避免多重條件選擇語(yǔ)句。它提供了對(duì)開(kāi)放—封閉原則的完美支持,將算法封裝在獨(dú)立的 strategy 中,使得它們易于切換,易于理解,易于擴(kuò)展。

          const?commodity?=?new?Map([
          ??['phone',?1999],
          ??['computer',?9999],
          ??['television',?2999],
          ??['gameBoy',?3999],
          ])

          const?price?=?(name)?=>?{
          ??return?commodity.get(name)
          }
          price('phone')?//?1999

          includes 的優(yōu)化

          includes 是 ES7 新增的 API,與 indexOf 不同的是 includes 直接返回的是 Boolean 值,indexOf 則 返回的索引值, 數(shù)組和字符串都有 includes 方法。

          需求:我們來(lái)實(shí)現(xiàn)一個(gè)身份認(rèn)證方法,通過(guò)傳入身份 Id 返回對(duì)應(yīng)的驗(yàn)證結(jié)果

          傳統(tǒng)方法

          function?verifyIdentity(identityId)?{
          ??if?(identityId?==?1?||?identityId?==?2?||?identityId?==?3?||?identityId?==?4)?{
          ????return?'你的身份合法,請(qǐng)通行!'
          ??}?else?{
          ????return?'你的身份不合法'
          ??}
          }

          includes 優(yōu)化

          function?verifyIdentity(identityId)?{
          ??if?([1,?2,?3,?4].includes(identityId))?{
          ????return?'你的身份合法,請(qǐng)通行!'
          ??}?else?{
          ????return?'你的身份不合法'
          ??}
          }

          for 循環(huán)

          在 JavaScript 中,我們可以使用 for()while()for(in)for(of)幾種循環(huán),事實(shí)上,這三種循環(huán)中 for(in) 的效率極差,因?yàn)樗枰樵兩⒘墟I,所以應(yīng)該盡量少用。

          for 循環(huán)是最傳統(tǒng)的語(yǔ)句,它以變量 i 作為索引,以跟蹤訪問(wèn)的位置,對(duì)數(shù)組進(jìn)行操作。

          var?arr?=?['a',?'b',?'c']
          for?(var?i?=?0;?i???console.log(arr[i])?//結(jié)果依次a,b,c
          }

          以上的方法有一個(gè)問(wèn)題:就是當(dāng)數(shù)組的長(zhǎng)度到達(dá)百萬(wàn)級(jí)時(shí),arr.length 就要計(jì)算一百萬(wàn)次,這是相當(dāng)耗性能的。所以可以采用以下方法就行改良。

          var?arr?=?['a',?'b',?'c']
          for?(var?i?=?0,?length?=?arr.length;?i???console.log(arr[i])?//結(jié)果依次a,b,c
          }

          此時(shí) arr.length 只需要計(jì)算一次,優(yōu)化了性能。

          for-in 一般用來(lái)來(lái)遍歷對(duì)象的屬性的,不過(guò)屬性需要 enumerable(可枚舉)才能被讀取到。同時(shí) for-in 也可以遍歷數(shù)組,遍歷數(shù)組的時(shí)候遍歷的是數(shù)組的下標(biāo)值。

          var?obj?=?{?0:?'a',?1:?'b',?2:?'c'?}
          for?(var?key?in?obj)?{
          ??console.log(key)?//結(jié)果為依次為0,1,2
          }

          var?arr?=?['a',?'b',?'c']
          for?(var?key?in?a)?{
          ??console.log(key)?//結(jié)果為依次為0,1,2
          }

          for-of 語(yǔ)句看著有點(diǎn)像 for-in 語(yǔ)句,但是和 for-of 語(yǔ)句不同的是它不可以循環(huán)對(duì)象,只能循環(huán)數(shù)組。

          var?arr?=?['a',?'b',?'c']
          for?(var?value?of?arr)?{
          ??console.log(value)?//?結(jié)果依次為a,b,c
          }

          for-offor-in 循環(huán)遍歷數(shù)組更好。for-of 只要具有 Iterator 接口的數(shù)據(jù)結(jié)構(gòu),都可以使用它迭代成員。它直接讀取的是鍵值。for-in 需要窮舉對(duì)象的所有屬性,包括自定義的添加的屬性也能遍歷到。且 for-inkeyString 類型,有轉(zhuǎn)換過(guò)程,開(kāi)銷比較大。

          所以在開(kāi)發(fā)過(guò)程中循環(huán)數(shù)組盡量避免使用 for-in

          數(shù)組去重

          數(shù)組去重是實(shí)際開(kāi)發(fā)處理數(shù)據(jù)中經(jīng)常遇到的,方法有很多,這里就不一一例舉了。

          1、最傳統(tǒng)的方法:利用數(shù)組的 indexOf 下標(biāo)屬性來(lái)查詢。

          function?unique4(arr)?{
          ??var?newArr?=?[]
          ??for?(var?i?=?0;?i?????if?(newArr.indexOf(arr[i])?===?-1)?{
          ??????newArr.push(arr[i])
          ????}
          ??}
          ??return?newArr
          }
          console.log(unique4([1,?1,?2,?3,?5,?3,?1,?5,?6,?7,?4]))
          //?[1,?2,?3,?5,?6,?7,?4]

          2、優(yōu)化:利用 ES6 的 Set 方法。

          Set 本身是一個(gè)構(gòu)造函數(shù),用來(lái)生成 Set 數(shù)據(jù)結(jié)構(gòu)。Set 函數(shù)可以接受一個(gè)數(shù)組(或者具有 iterable 接口的其他數(shù)據(jù)結(jié)構(gòu))作為參數(shù),用來(lái)初始化。Set 對(duì)象允許你存儲(chǔ)任何類型的值,無(wú)論是原始值或者是對(duì)象引用。它類似于數(shù)組,但是成員的值都是唯一的,沒(méi)有重復(fù)的值。

          function?unique4(arr)?{
          ??return?Array.from(new?Set(arr))?//?利用Array.from將Set結(jié)構(gòu)轉(zhuǎn)換成數(shù)組
          }
          console.log(unique4([1,?1,?2,?3,?5,?3,?1,?5,?6,?7,?4]))
          //?[1,?2,?3,?5,?6,?7,?4]

          箭頭函數(shù)

          箭頭函數(shù)表達(dá)式的語(yǔ)法比函數(shù)表達(dá)式更簡(jiǎn)潔。所以在開(kāi)發(fā)中更推薦使用箭頭函數(shù)。特別是在 vue 項(xiàng)目中,使用箭頭函數(shù)不需要在更 this 重新賦一個(gè)變量。

          //?使用functions
          var?arr?=?[5,?3,?2,?9,?1]
          var?arrFunc?=?arr.map(function?(x)?{
          ??return?x?*?x
          })
          console.log(arrFunc)

          //?使用箭頭函數(shù)
          var?arr?=?[5,?3,?2,?9,?1]
          var?arrFunc?=?arr.map((x)?=>?x?*?x)

          要注意的是,箭頭函數(shù)不綁定 arguments,取而代之用 rest 參數(shù)…解決。

          //?不能使用?arguments
          let?fun1?=?(b)?=>?{
          ??console.log(arguments)
          }
          fun1(2,?92,?32,?32)?//?Uncaught?ReferenceError:?arguments?is?not?defined

          //?使用rest?參數(shù)
          let?fun2?=?(...c)?=>?{
          ??console.log(c)
          }
          fun2(3,?82,?32,?11323)?//?[3,?82,?32,?11323]

          Dom 的創(chuàng)建

          創(chuàng)建多個(gè) dom 元素時(shí),先將元素 appendDocumentFragment 中,最后統(tǒng)一將 DocumentFragment 添加到頁(yè)面。

          常規(guī)方法;

          for?(var?i?=?0;?i?1000;?i++)?{
          ??var?el?=?document.createElement('p')
          ??el.innerHTML?=?i
          ??document.body.appendChild(el)
          }

          使用 DocumentFragment 優(yōu)化多次 append

          var?frag?=?document.createDocumentFragment()
          for?(var?i?=?0;?i?1000;?i++)?{
          ??var?el?=?document.createElement('p')
          ??el.innerHTML?=?i
          ??frag.appendChild(el)
          }
          document.body.appendChild(frag)

          更優(yōu)的方法:使用一次 innerHTML 賦值代替構(gòu)建 dom 元素

          var?html?=?[]
          for?(var?i?=?0;?i?1000;?i++)?{
          ??html.push('

          '?+?i?+?'

          '
          )
          }
          document.body.innerHTML?=?html.join('')

          內(nèi)存泄漏

          系統(tǒng)進(jìn)程不再用到的內(nèi)存,沒(méi)有及時(shí)釋放,就叫做內(nèi)存泄漏(memory leak)。當(dāng)內(nèi)存占用越來(lái)越高,輕則影響系統(tǒng)性能,重則導(dǎo)致進(jìn)程崩潰。

          引起內(nèi)存泄漏的原因

          全局變量

          1、未聲明變量或者使用 this 創(chuàng)建的變量(this 的指向是 window)都會(huì)引起內(nèi)存泄漏

          function?fn()?{
          ??a?=?"Actually,?I'm?a?global?variable"
          }
          fn()

          function?fn()?{
          ??this.a?=?"Actually,?I'm?a?global?variable"
          }
          fn()

          解決方法:

          • 避免創(chuàng)建全局變量
          • 使用嚴(yán)格模式,在 JavaScript 文件頭部或者函數(shù)的頂部加上 use strict

          2、在 vue 單頁(yè)面應(yīng)用,聲明的全局變量在切換頁(yè)面的時(shí)候沒(méi)有清空


          ??<div?id="home">
          ????這里是首頁(yè)
          ??div>
          ??export?default?{
          ????mounted()?{
          ??????window.test?=?{
          ????????//?此處在全局window對(duì)象中引用了本頁(yè)面的dom對(duì)象
          ????????name:?'home',
          ????????node:?document.getElementById('home')
          ??????}
          ????}
          ??}

          解決方案: 在頁(yè)面卸載的時(shí)候順便處理掉該引用。

          destroyed?()?{
          ??window.test?=?null?//?頁(yè)面卸載的時(shí)候解除引用
          }

          閉包

          閉包引起的內(nèi)存泄漏原因:閉包可以維持函數(shù)內(nèi)局部變量,使其得不到釋放。

          function?fn()?{
          ??var?a?=?"I'm?a"
          ??return?function?()?{
          ????console.log(a)
          ??}
          }

          解決:將事件處理函數(shù)定義在外部,解除閉包,或者在定義事件處理函數(shù)的外部函數(shù)中,刪除對(duì) dom 的引用。

          定時(shí)器或事件監(jiān)聽(tīng)

          由于項(xiàng)目中有些頁(yè)面難免會(huì)碰到需要定時(shí)器或者事件監(jiān)聽(tīng)。但是在離開(kāi)當(dāng)前頁(yè)面的時(shí)候,定時(shí)器如果不及時(shí)合理地清除,會(huì)造成業(yè)務(wù)邏輯混亂甚至應(yīng)用卡死的情況,這個(gè)時(shí)就需要清除定時(shí)器事件監(jiān)聽(tīng),即在頁(yè)面卸載(關(guān)閉)的生命周期函數(shù)里,清除定時(shí)器。

          methods:{
          ??resizeFun?()?{
          ????this.tableHeight?=?window.innerHeight?-?document.getElementById('table').offsetTop?-?128
          ??},
          ??setTimer()?{
          ????this.timer?=?setInterval(()?=>?{?})
          ??},
          ??clearTimer()?{//清除定時(shí)器
          ??clearInterval(this.timer)
          ????this.timer?=?null
          ?}
          },
          mounted()?{
          ??this.setTimer()
          ??window.addEventListener('resize',?this.resizeFun)
          },
          beforeDestroy()?{
          ??window.removeEventListener('resize',?this.resizeFun)
          ??this.clearTimer()
          }

          防抖與節(jié)流

          在前端開(kāi)發(fā)的過(guò)程中,我們經(jīng)常會(huì)需要綁定一些持續(xù)觸發(fā)的事件,如 resizescrollmousemove 等等,但有些時(shí)候我們并不希望在事件持續(xù)觸發(fā)的過(guò)程中那么頻繁地去執(zhí)行函數(shù)。這時(shí)候就用到防抖與節(jié)流。

          案例 1:遠(yuǎn)程搜索時(shí)需要通過(guò)接口動(dòng)態(tài)的獲取數(shù)據(jù),若是每次用戶輸入都接口請(qǐng)求,是浪費(fèi)帶寬和性能的。

          "remoteMethod">
          ????<Option?v-for="item?in?temoteList"?:value="item.value"?:key="item.id">{{item.label}}Option>
          </Select>



          上面代碼中,

          <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>
                    无码日韩一区 | 欧美高清免费无码 | 成人免费小视频 | 手机看片91 | 开心五月天激情成人网 |