亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Javascript前端優(yōu)化代碼

 更新時(shí)間:2021年04月27日 11:17:56   作者:淺笑·  
這篇文章主要介紹了Javascript前端優(yōu)化代碼,對性能優(yōu)化感興趣的同學(xué),可以參考下

if 判斷的優(yōu)化

JavaScript條件語句在我們平時(shí)的開發(fā)中是不可避免要用到的,但是很多時(shí)候我們的代碼寫的并不好,一連串的if-else或者多重嵌套判斷都會使得代碼很臃腫,下面舉例進(jìn)行優(yōu)化。

需求:現(xiàn)在有 4 個產(chǎn)品,分別是手機(jī)、電腦、電視機(jī)、游戲機(jī),當(dāng)然每個產(chǎn)品顯示的價(jià)格不一樣。

1、最簡單的方法: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):代碼太長了,維護(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ù)和思想,可以有效地避免多重條件選擇語句。它提供了對開放—封閉原則的完美支持,將算法封裝在獨(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方法。

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

傳統(tǒng)方法

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

includes優(yōu)化

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

for 循環(huán)

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

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

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

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

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

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

for-in一般用來來遍歷對象的屬性的,不過屬性需要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語句看著有點(diǎn)像for-in語句,但是和for-of語句不同的是它不可以循環(huán)對象,只能循環(huán)數(shù)組。

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

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

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

數(shù)組去重

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

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

function unique4(arr) {
  var newArr = []
  for (var i = 0; i < arr.length; 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òu)造函數(shù),用來生成Set數(shù)據(jù)結(jié)構(gòu)。Set函數(shù)可以接受一個數(shù)組(或者具有 iterable 接口的其他數(shù)據(jù)結(jié)構(gòu))作為參數(shù),用來初始化。Set對象允許你存儲任何類型的值,無論是原始值或者是對象引用。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(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á)式的語法比函數(shù)表達(dá)式更簡潔。所以在開發(fā)中更推薦使用箭頭函數(shù)。特別是在vue項(xiàng)目中,使用箭頭函數(shù)不需要在更this重新賦一個變量。

// 使用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)建多個 dom 元素時(shí),先將元素append到DocumentFragment中,最后統(tǒng)一將DocumentFragment添加到頁面。

常規(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('<p>' + i + '</p>')
}
document.body.innerHTML = html.join('')

內(nèi)存泄漏

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

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

全局變量

1、未聲明變量或者使用this創(chuàng)建的變量(this的指向是window)都會引起內(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īng)用,聲明的全局變量在切換頁面的時(shí)候沒有清空

<template>
  <div id="home">
    這里是首頁
  </div>
</template>

<script>
  export default {
    mounted() {
      window.test = {
        // 此處在全局window對象中引用了本頁面的dom對象
        name: 'home',
        node: document.getElementById('home')
      }
    }
  }
</script>

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

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

閉包

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

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

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

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

由于項(xiàng)目中有些頁面難免會碰到需要定時(shí)器或者事件監(jiān)聽。但是在離開當(dāng)前頁面的時(shí)候,定時(shí)器如果不及時(shí)合理地清除,會造成業(yè)務(wù)邏輯混亂甚至應(yīng)用卡死的情況,這個時(shí)就需要清除定時(shí)器事件監(jiān)聽,即在頁面卸載(關(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é)流

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

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

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

<script>
function debounce(fn, wait) {
  let timeout = null
  return function () {
    if (timeout !== null) clearTimeout(timeout)
    timeout = setTimeout(fn, wait)
  }
}

export default {
  methods:{
    remoteMethod:debounce(function (query) {
        // to do ...
    }, 200),
  }
}
<script>

案例 2:持續(xù)觸發(fā)scroll事件時(shí),并不立即執(zhí)行handle函數(shù),當(dāng) 1000 毫秒內(nèi)沒有觸發(fā)scroll事件時(shí),才會延時(shí)觸發(fā)一次handle函數(shù)。

function debounce(fn, wait) {
  let timeout = null
  return function () {
    if (timeout !== null) clearTimeout(timeout)
    timeout = setTimeout(fn, wait)
  }
}
function handle() {
  console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))

異步加載js

默認(rèn)情況下,瀏覽器是同步加載js腳本,解析 html 過程中,遇到<script>標(biāo)簽就會停下來,等腳本下載、解析、執(zhí)行完后,再繼續(xù)向下解析渲染。

如果 js 文件體積比較大,下載時(shí)間就會很長,容易造成瀏覽器堵塞,瀏覽器頁面會呈現(xiàn)出“白屏”效果,用戶會感覺瀏覽器“卡死了”,沒有響應(yīng)。此時(shí),我們可以讓 js 腳本異步加載、執(zhí)行。

<script src="path/to/home.js" defer></script>
<script src="path/to/home.js" async></script>

上面代碼中,<script>標(biāo)簽分別有defer和async屬性,瀏覽器識別到這 2 個屬性時(shí) js 就會異步加載。也就是說,瀏覽器不會等待這個腳本下載、執(zhí)行完畢后再向后執(zhí)行,而是直接繼續(xù)向后執(zhí)行

defer 與 async 區(qū)別:

  • defer:DOM 結(jié)構(gòu)完全生成,以及其他腳本執(zhí)行完成,才會執(zhí)行(渲染完再執(zhí)行)。有多個defer腳本時(shí),會按照頁面出現(xiàn)的順序依次加載、執(zhí)行。
  • async:一旦下載完成,渲染引擎就會中斷渲染,執(zhí)行這個腳本以后,再繼續(xù)渲染(下載完就執(zhí)行)。有多個async腳本時(shí),不能保證按照頁面出現(xiàn)順序加載、執(zhí)行

以上就是Javascript前端優(yōu)化代碼的詳細(xì)內(nèi)容,更多關(guān)于Javascript優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • js彈出窗口之彈出層的小例子

    js彈出窗口之彈出層的小例子

    js彈出窗口之彈出層的小例子,需要的朋友可以參考一下
    2013-06-06
  • 微信小程序云開發(fā)之使用云存儲

    微信小程序云開發(fā)之使用云存儲

    這篇文章主要為大家詳細(xì)介紹了微信小程序云開發(fā)之使用云存儲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • JavaScript如何刪除對象的某個屬性詳析

    JavaScript如何刪除對象的某個屬性詳析

    這篇文章主要給大家介紹了關(guān)于JavaScript如何刪除對象的某個屬性的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • JS實(shí)現(xiàn)的自定義map方法示例

    JS實(shí)現(xiàn)的自定義map方法示例

    這篇文章主要介紹了JS實(shí)現(xiàn)的自定義map方法,結(jié)合實(shí)例形式分析了javascript自定義map相關(guān)的json數(shù)組定義、遍歷、添加、刪除、讀取等相關(guān)操作技巧,需要的朋友可以參考下
    2019-05-05
  • js點(diǎn)擊文本框后才加載驗(yàn)證碼實(shí)例代碼

    js點(diǎn)擊文本框后才加載驗(yàn)證碼實(shí)例代碼

    這篇文章是一段關(guān)于js點(diǎn)擊文本框后才加載驗(yàn)證碼實(shí)例代碼,而不是直接顯示驗(yàn)證碼,感興趣的小伙伴們可以參考一下
    2015-10-10
  • JavaScript中定時(shí)控制Throttle、Debounce和Immediate詳解

    JavaScript中定時(shí)控制Throttle、Debounce和Immediate詳解

    大家可能都知道JavaScript遵循事件驅(qū)動的編程范例,這意味著一些行為可以激活一些響應(yīng),并且這些響應(yīng)僅在發(fā)生特定的行為時(shí)才被激活。這篇文章將給大家詳細(xì)介紹JavaScript中的定時(shí)控制Throttle、Debounce和Immediate,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-11-11
  • 判斷ie的兩種簡單方法

    判斷ie的兩種簡單方法

    判斷ie想必大家都會寫吧,如何將判斷條件變得簡單呢,也許大家并不是很清楚,感興趣的大家可以參考下本文,或許會有所收獲
    2013-08-08
  • javascript獲取元素偏移量的方法有哪些

    javascript獲取元素偏移量的方法有哪些

    javascript中可以通過四個屬性獲得元素的偏移量,offsetHeight、offsetWidth、offsetLeft、offsetTop,下面為大家解釋下各屬性的含義
    2014-06-06
  • JavaScript運(yùn)行過程中的“預(yù)編譯階段”和“執(zhí)行階段”

    JavaScript運(yùn)行過程中的“預(yù)編譯階段”和“執(zhí)行階段”

    這篇文章主要介紹了JavaScript運(yùn)行過程中的“預(yù)編譯階段”和“執(zhí)行階段”的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • JS獲取下拉框顯示值和判斷單選按鈕的方法

    JS獲取下拉框顯示值和判斷單選按鈕的方法

    這篇文章主要介紹了JS獲取下拉框顯示值和判斷單選按鈕的方法,實(shí)例分析了javascript針對html下拉框及單選按鈕的相關(guān)操作技巧,需要的朋友可以參考下
    2015-07-07

最新評論