js實(shí)戰(zhàn)優(yōu)化001

前言

本文開始針對項(xiàng)目中總結(jié)出來的關(guān)于js基礎(chǔ)知識的代碼優(yōu)化技巧進(jìn)行每個(gè)細(xì)節(jié)點(diǎn)的分析,后續(xù)還會針對某個(gè)專題的分析。

案例說明

if針對同一關(guān)鍵值多條件的判斷

針對key進(jìn)行多條件判斷,而其中的多條件可能有些可以歸為一類,因?yàn)槠鋱?zhí)行的代碼是相同的

//優(yōu)化前
if(key === 1 || key ===3 || key===9){
//some codes here
}
//優(yōu)化后
let codesOptionArr = [1,3,9]
if(codesOptionArr.includes(key)){
//some codes here
}

針對多case,分別返回或者設(shè)置不同值,代碼段很簡單

需要根據(jù)不同的值情況,來返回或者設(shè)定對應(yīng)的值,相信很多人會說用switch來進(jìn)行優(yōu)化,其實(shí)用對象字面量會更好,也更方便維護(hù)和復(fù)用。比較常見的是前端常見的一些枚舉數(shù)據(jù)以及固定值。

//優(yōu)化前
let str =''
switch(type){
case 'name': str ='姓名'
break
case 'sex': str ='性別'
break
} 
//優(yōu)化后
function getTypeStr (type){ 
if(!type) return ''
let dict = {
name:'姓名',
sex:'性別'
}
return dict[type] || type
}

let str = getTypeStr(type)

少寫嵌套,盡早返回

缺點(diǎn)除了邏輯分不清楚,還會導(dǎo)致代碼執(zhí)行性能低,在執(zhí)行完需要的邏輯之后不能跳出方法。所以建議針對已經(jīng)符合返回的情況下 ,就返回對應(yīng)的邏輯,不再進(jìn)行多余的判斷。

//優(yōu)化前
function judgeAge(age){
let str =''
if(age && !isNaN(age) && age> 0  ){
 if(age <18) {
   str = '還是未成年 '
   } else {
   str = '符合要求'
   }
} else {
str = '年齡不合法'
}
return str
}

//優(yōu)化后
function judgeAge(age){
   if(!age || isNaN(age) || age < 0  ){
       return '年齡不合法'
   }
   if(age<18) return '還是未成年'
   else{
       return '符合要求'
   }
}

方法內(nèi)的返回或者對應(yīng)關(guān)系具有關(guān)聯(lián)關(guān)系,或者可以進(jìn)行一定的代碼關(guān)聯(lián)設(shè)計(jì),這里不針對對象字面量。

//優(yōu)化前
let str =''
switch(number) {
case 0 : str = '沒有任何收入'
break
case 1 :str='您有一枚硬幣了'
break
} 
return str
//優(yōu)化后
let descArr = ['沒有任何收入','您有一枚硬幣了']
return descArr[number]

使用函數(shù)默認(rèn)值和解構(gòu)

也許你之前沒有用過函數(shù)默認(rèn)值,也沒有分析過解構(gòu)能帶來什么優(yōu)化。

// 優(yōu)化前
function fn(age){
let _age = age || 0
console.log(_age)
}
// 優(yōu)化后
function fn(age = 0){
console.log(age)
}
// 優(yōu)化前
function fn(person){
if(person && person.name) {
console.log(pserson.name || '')
}
}
// 優(yōu)化后
function fn({name}){
  console.log(name || '')
}

合并條件與執(zhí)行語句

在庫代碼中經(jīng)??吹揭恍┡袛鄺l件與執(zhí)行語句、返回語句寫在一起,非常簡潔高效,也可讀性較高。

let  getArrlen= (str,arr) => {
if(!(arr instanceof(Array))) return 'arr is not arr '
return arr && arr.length 

} 

批量對象屬性賦值

使用場景:主要是針對需要把對象的一些屬性批量的賦值到另外一個(gè)對象上,然后如果你的屬性很多可能要寫很多賦值語句。(前提是屬性名一般是相同的)

說明:可能有人會問為什么不直接用這個(gè)對象,答案也很簡單,如果可以直接用,當(dāng)然直接用是最好的,我自己在寫接口param的時(shí)候,就會注意這些,需要傳參的部分封裝到一個(gè)特殊的對象里,然后進(jìn)行data的綁定,這樣需要的時(shí)候直接用傳參對象。但這里討論的不是這種情況。

//優(yōu)化前
let data = {}
data.name = this.form.name
data.len = this.form.len
data.amount = this.form.amount
//優(yōu)化版本一 :利用對象的解構(gòu)
let {name,len,amount} = this.form 
//利用對象解構(gòu)還可以支持屬性名變更的情況
let {name,len:length,amount:money} = this.form
let data = {name,len,amount}
//  優(yōu)化后 
let data = this.setProps[{source:this.form,propArr:['name','len','amount']}]
//優(yōu)化版本二 :可以支持批量的導(dǎo)入需要賦值的,對于拷貝對象,用source屬性承接,而需要賦值的屬性用propArr承接
//在方法中用json的相關(guān)方法支持了簡單的對象深拷貝
// 批量加載對象屬性,支持傳入數(shù)組[{source:sourceObj,propArr:[]}]  
setProps(arr) {
    if (arr.length <= 0) return {}
    return arr.reduce((acc, item) => {
         item.propArr.reduce((acc, prop) => {
          if (typeof item.source[prop] === 'object') {
            acc[prop] = JSON.parse(JSON.stringify(item.source[prop]))
         } else {
                acc[prop] = item.source[prop]
                }
            return acc
            }, acc)
        return acc
    }, {})
}

拓展思考:像這種代碼如果你的vue代碼里經(jīng)常寫,不妨在你的mixins中混入這個(gè)方法,可以為你的頁面節(jié)省大量的代碼空間。

批量變量重置

在我們的代碼中經(jīng)常會遇到吧一些變量進(jìn)行重置,這部分代碼重復(fù)率很高又沒有技術(shù)含量,所以我寫一個(gè)工具方法進(jìn)行簡單的支持,代碼優(yōu)化。

//優(yōu)化前
this.search = false 
this.data = []
this.cur_page = 1
this.pageNo = 1
this.totalCount = 0
this.processType = ''
this.person = ''
this.keyword = ''
this.taskStatus = ''
this.stdate = []
this.processStatus = ''
//  優(yōu)化后
this.resetVars([this.data,this.processType,this.person,this.keyword,this.taskStatus])
 /**
      * @author zhangbing 
      * @param [] arr 需要重置的數(shù)組變量
      * @param {*} options 配置對象 對于這里的重置規(guī)則如果不符合需求的可以自定義option字典,然后用instanceof 判斷類型(todo)
      */   
    resetVars(arr, options) { 
        if (!arr || arr.length === 0) return 
        let _options = {
            object: {},
            string: '',
            number: 0,
            boolean: true,
            null: null,
            undefined: undefined
        }
        _options = options ? Object.assign({}, _options, options) : _options
        return arr.map(item => { 
            if (_options.includes(typeof item)) {
                item = _options[typeof item]
            } else { 
                // 不存在重置類型的 重置為字符串
                item = ''
            }
            return item
        })

    }

拓展思考:像這種代碼如果你的vue代碼里經(jīng)常寫,不妨在你的mixins中混入這個(gè)方法,可以為你的頁面節(jié)省大量的代碼空間。

對象的淺拷貝與深拷貝

在js中,我們可以用等號來進(jìn)行基本數(shù)據(jù)類型的賦值,而對于復(fù)雜數(shù)據(jù)類型也就是對象類型,其等號賦予的是對象地址,不能實(shí)現(xiàn)拷貝的目的。而我們知道的Object.assign實(shí)現(xiàn)的也是對象的淺拷貝。
所以一般情況下,如果你不確定的情況下,如果發(fā)現(xiàn)對象屬性值是對象類型,需要遞歸拷貝。核心知識點(diǎn)是:typeof source[prop] === 'object' ,return Object.assign(target[prop],source[prop]),直到對象屬性為基本類型.

這里所講的不是這部分,而是利用JSON的轉(zhuǎn)化方法來實(shí)現(xiàn)簡單的對象深拷貝。當(dāng)然這種方法是有弊端的,詳情參考我另一篇文章利用json序列化對象的問題

let target = JSON.parse(JSON.stringify(source))

更多

以上方法只是根據(jù)個(gè)人經(jīng)驗(yàn)和想法進(jìn)行的一些可優(yōu)化的思維拓展,有些可能是矯枉過正,但代碼的優(yōu)化道路上,從來都是要特定場景下解決特定需求的,為的還是要讓使用更簡單,讓使用者更習(xí)慣、高效的開發(fā),提前或者滯后的將代碼進(jìn)行優(yōu)化重構(gòu)固然都是錯(cuò)的,但如果一點(diǎn)點(diǎn)優(yōu)化的思考和什么程度應(yīng)該去做重構(gòu)了不去探索就進(jìn)步太慢了。

其他文章推薦

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容