相信不少小夥伴,在接手別人的二手代碼時,是否都有一個感覺,一無註釋,二無格式,代碼冗雜,一個簡單的功能用了N個方法實現,頓時感受,一個腦殼兩個大,俗話說好的代碼使人賞心悅目,冗雜的代碼讓人心生不快。我的也是接手了其餘同事或是外包或是通過多人手的代碼的一點感悟,因而我的總結了如下幾個代碼優化的方法前端
先來看一個簡單的例子:web
需求是星期回顯,傳
1
回顯星期一
,傳7
回顯星期日
,其餘類推,無效回顯空字符串;相似的需求還有回顯月份後端
第一種實現方法: switch
實現數組
function previewWeek(i){
switch(i){
case 1:
return '星期一'
break;
case 2:
return '星期二'
break;
case 3:
return '星期三'
break;
case 4:
return '星期四'
break;
case 5:
return '星期五'
break;
case 6:
return '星期六'
break;
case 7:
return '星期日'
break;
default:
return ''
}
}
複製代碼
第二種實現方法: if else
實現ide
function previewWeek(i){
if(i==1){
return '星期一'
}else if(i==2){
return '星期二'
}else if(i==3){
return '星期三'
}else if(i==4){
return '星期四'
}else if(i==5){
return '星期五'
}else if(i==6){
return '星期六'
}else if(i==7){
return '星期日'
}else{
return ''
}
}
複製代碼
第三種實現方法: 三元實現函數
function previewWeek(i){
return i==1?'星期一':
i==2?'星期二':
i==3?'星期三':
i==4?'星期四':
i==5?'星期五':
i==6?'星期六':
i==7?'星期日':''
}
複製代碼
感受代碼量少了不少,是否咱們還能夠優化呢?不難發現代碼中有不少重複的代碼(包括中文)工具
第四種實現方法: 數組+索引優化代碼post
function previewWeek(i){
return i>0 && i<8 ?'星期'+['一','二','三','四','五','六','日'][i-1]:''
}
複製代碼
總結:有些時候,重複的代碼比較多,咱們能夠把重複的代碼提出來,觀察剩下的動態的值,若是能夠與索引創建關係更好,能夠進一步簡化咱們的代碼優化
感謝 CherishXY web前端
補充了能夠用map,集思廣益,特意補充 map 優化方法ui
第五種實現方法: map優化代碼
function previewWeek(i){
let weeksMap = new Map([
[1, '一'],
[2, '二'],
[3, '三'],
[4, '四'],
[5, '五'],
[6, '六'],
[7, '日']
]);
return weeksMap.get(i)?'星期'+weeksMap.get(i):''
}
複製代碼
includes
是 ES7 新增的API,與indexOf
不一樣的是includes
直接返回的是Boolean
值,indexOf
則 返回的索引值, 數組和字符串都有includes
方法,具體能夠查看 Array.prototype.includes 和 String.prototype.includes
先來看一個簡單的例子:以 數組的 includes
爲例子,字符串的includes
相似
咱們來實現一個身份認證方法,經過傳入身份Id返回對應的驗證結果
通常實現:||
function verifyIdentity(identityId){
if(identityId==1 || identityId==2 || identityId==3 || identityId==4){
return '你的身份合法,請通行!'
}else{
return '你的身份未知,警告!'
}
}
複製代碼
此種寫法的缺點是在須要驗證的身份Id 變的不少的時候,重複代碼量跟着變多
初級優化實現:includes
function verifyIdentity(identityId){
if([1,2,3,4].includes(identityId)){
return '你的身份合法,請通行!'
}else{
return '你的身份未知,警告!'
}
}
複製代碼
此種寫法的在須要驗證的身份Id 變多的時候,只須要在includes前的數組裏後面繼續添加就行,缺點是仍然佔用4行
最終優化實現:includes + 三元
function verifyIdentity(identityId){
return [1,2,3,4].includes(identityId)?'你的身份合法,請通行!':'你的身份未知,警告!'
}
複製代碼
此種寫法我的比較推薦,從維護和擴展方面比較友好
從一個例子提及:
寫個查詢元素的方法
通常寫法
/** * @param {String } selector : 元素選擇器 * @param {Boolean } isAll :是否獲取全部 */
function getElement(selector,isAll = false){
if(isAll){
return document.querySelectorAll(selector)
}else{
return document.querySelector(selector)
}
}
複製代碼
三元寫法
function getElement(selector,isAll = false){
return isAll?document.querySelectorAll(selector):document.querySelector(selector)
}
複製代碼
三元定點
動態的數據發生的地點,針對性的優化
function getElement(selector,isAll = false){
return document[ 'querySelector'+(isAll?'All':'') ](selector)
}
複製代碼
不難發現,動態的數據發生在[]裏面的小括號裏面,經過定點優化進一步減小了咱們的代碼量,此種衍生的版本比較多
例如:爲 container
類元素根據isShow
來顯示隱藏
// jQuery 中是否常常這麼幹?
$('.container')[ isShow?'show' : 'hide' ]()
複製代碼
示例:
let color = "red"
function printBlackBackground(){
console.log('black')
}
function printRedBackground(){
console.log('red')
}
function printBlueBackground(){
console.log('blue')
}
function printGreenBackground(){
console.log('green')
}
function printYellowBackground(){
console.log('yellow')
}
switch(color) {
case 'black':
printBlackBackground();
break;
case 'red':
printRedBackground();
break;
case 'blue':
printBlueBackground();
break;
case 'green':
printGreenBackground();
break;
default:
printYellowBackground();
}
複製代碼
待優化部分爲switch
咱們用對象形式創建key-value映射關係
let colorMap = {
black: printBlackBackground,
red: printRedBackground,
blue: printBlueBackground,
green: printGreenBackground,
yellow: printYellowBackground
}
colorMap[color]? colorMap[color]() : printYellowBackground()
複製代碼
備註:此種方法借鑑於其餘網友
優化前
function request(options){
let method = options.method?options.method:'GET'
let data = options.data?options.data:{}
//...
}
複製代碼
優化後
function request(options){
let method = options.method || 'GET'
let data = options.data || {}
//...
}
複製代碼
基於 ES6 優化後
function request(method='GET',data={}){
//...
}
複製代碼
有些時候咱們封裝請求,須要準備本身的默認參數,而後與傳入的參數進行合併獲得最終的請求參數
function request(options){
let opt = Object.assign({
method:'POST',
data:{}
},options)
//opt.data.fxiedProps = 1 ; //有時,請求裏需求固定存在一個key值
return opt
}
複製代碼
優化前
function log(){
console.log('前面的flag爲真,就會看到我')
}
let flag = true
if(flag){
log()
}
複製代碼
優化後
function log(){
console.log('前面的flag爲真,就會看到我')
}
let flag = true
flag && log()
複製代碼
示例2:
if(a && b){
c()
}
//=> 優化後 a && b && c()
//其餘類推
複製代碼
此種寫法項目中使用較多
優化前
function demo(flag){
if(flag){
return "真"
}else{
return "假"
}
}
複製代碼
優化後
function demo(flag){
return flag? "真" : "假"
}
複製代碼
從一個例子提及: demo 方法傳true
執行 success
方法,傳 false
執行 error
方法
function success(){
console.log("success")
}
function fail(){
console.log("fail")
}
function demo(flag){
if(flag){
success()
}else{
fail()
}
}
複製代碼
看了以上多個例子後,你也許會這麼優化:
function demo(flag){
flag?success():fail()
}
複製代碼
這個應該是最經常使用的,
true
就執行success
,false
就執行fail
補充一個不常見的
// 若是你不能保證 你所傳的參數必定是布爾值的話 用這種
function demo(flag){
[false,true].includes(flag) && [fail,success][Number(flag)]()
}
// false 轉成 0 ,對應執行success ,true 轉成 1,對應執行 fail
// 若是你能保證 你所傳的參數必定是布爾值的話 用這種
function demo(flag){
[fail,success][Number(flag)]()
}
複製代碼
此種優化策略,結合了 布爾值的false和true是能夠轉成 0 和1,所以能夠拿來當索引使用
封裝一個獲取位置的方法:getPosition
優化前
function getPosition(direction){
if(direction == "left"){
return "左"
}else if(direction == "right"){
return "右"
}else if(direction == "top"){
return "上"
}else if(direction == "bottom"){
return "下"
}else{
return "未知"
}
}
複製代碼
優化後
function getPosition(direction){
return ({
left:"左",
right:"右",
top:"上",
bottom:"下"
})[direction] || "未知"
}
複製代碼
咱們作個權限按鈕,不一樣角色登陸一個系統,點擊同個按鈕執行不一樣的業務邏輯
優化前
let role = 'admin' //模擬登陸接口返回的角色
document.querySelector('#btn').addEventListener( 'click' , function(){
if(role == 'admin'){
console.log('管理員點擊此按鈕執行的業務邏輯')
}else if(role == 'subAdmin'){
console.log('子管理員點擊此按鈕執行的業務邏輯')
}else if(role == 'mall'){
console.log('商場角色點擊此按鈕執行的業務邏輯')
}else if(role == 'parkingLot'){
console.log('停車場角色點擊此按鈕執行的業務邏輯')
}
})
複製代碼
以上代碼看上去沒有什麼問題,從便於維護和管理角度考慮,是須要優化的
優化後
let role = 'admin' //模擬登陸接口返回的角色
let btnPermissionsControl = {
admin:function(){
console.log('管理員點擊此按鈕執行的業務邏輯')
},
subAdmin:function(){
console.log('子管理員點擊此按鈕執行的業務邏輯')
},
mall:function(){
console.log('商場角色點擊此按鈕執行的業務邏輯')
},
parkingLot:function(){
console.log('停車場角色點擊此按鈕執行的業務邏輯')
}
}
document.querySelector('#btn').addEventListener( 'click' , btnPermissionsControl[role] )
複製代碼
優化後,你只須要維護一個對象便可
有些時候,後端返回的數據裏動態存在某個值,也就意味着,有時候有這個數據,有時候沒有,而後甩你一句話,「有就顯示,沒有就不顯示」,做爲前端的咱們天然很嚴謹
場景:後端大哥說了,給你返回的數據裏面的 若是有 userInfo
字段,而且userInfo
下面有hobby
字段而且有值就顯示 hobby
裏面的內容,不然頁面 hobby
這一塊不顯示
模擬後端返回的數據
let result = {
status:200,
codeMsg:'success',
data:{
userInfo:{
age:18,
hobby:['敲代碼','打籃球']
}
}
}
複製代碼
前端的嚴謹寫法
if(result.data){
if(result.data.userInfo){
if(result.data.userInfo.hobby){
if(Array.isArray(result.data.userInfo.hobby)){
if(result.data.userInfo.hobby.length){
//遍歷 result.data.userInfo.hobby 進行渲染顯示
}
}
}
}
}
複製代碼
用 &&
進行優化
第一種優化寫法
//成功拿到數據了 result
if ( result.data && result.data.userInfo &&
result.data.userInfo.hobby &&
Array.isArray(result.data.userInfo.hobby) &&
result.data.userInfo.hobby.length )
{
//遍歷 result.data.userInfo.hobby 進行渲染顯示
}
複製代碼
第二種優化寫法
//成功拿到數據了 result
result.data &&
result.data.userInfo &&
result.data.userInfo.hobby &&
Array.isArray(result.data.userInfo.hobby) &&
result.data.userInfo.hobby.length) &&
(()=>{
//遍歷 result.data.userInfo.hobby 進行渲染顯示
})()
複製代碼
第三種優化寫法
此種適合,嚴謹但又懶的前端
//成功拿到數據了 result
try {
if(result.data.userInfo.hobby.length){
//遍歷 result.data.userInfo.hobby 進行渲染顯示
}
} catch (error) {
}
複製代碼
此種採用
try catch
策略
let flag = a==1? true:false //優化 => let flag = a==1
//若是 變量 flag 用的地方多的話能夠用這個 flag 變量保存,
//若是就一兩個地方判斷使用,建議直接 if (a==1){}
let FLAG = b==1? false:true //優化 => let FLAG = !(b==1)
//此種策略採用取反
複製代碼
//聲明多個變量時
var firstName = '王'
var secondName = '兒'
var thirdName = '麻'
var lastName = '子'
// =>
// var firstName = '王',secondName = '兒',thirdName = '麻',lastName = '子'
//字符串拼接 使用 + 號頻繁時,用數組的join方法完成
//let result = firstName+sencondtName+threeName+lastName
// =>
//join
let result = [firstName,secondName,thirdName,lastName].join('')
複製代碼
若是你有更好的點子,歡迎留言
文中如有不許確或錯誤的地方,歡迎指出
往期文章 :前端開發中實用的工具方法