前言
本文開始針對項(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)步太慢了。