相信不少小伙伴,在接手别人的二手代码时,是否都有一个感觉,一无注释,二无格式,代码冗杂,一个简单的功能用了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('')
复制代码
若是你有更好的点子,欢迎留言
文中如有不许确或错误的地方,欢迎指出
往期文章 :前端开发中实用的工具方法