Js系列:js前端代码优化

118 阅读1分钟

文章来源:前端代码优化实用篇 - 掘金 (juejin.cn)

1.索引优化代码

需求

星期回显,传 1 回显 星期一,传 7 回显 星期日,其他类推,无效回显空字符串;类似的需求还有回显月份。

1.三元实现

 function previewWeek(i){
            return  i==1?'星期一':
                    i==2?'星期二':
                    i==3?'星期三':
                    i==4?'星期四':
                    i==5?'星期五':
                    i==6?'星期六':
                    i==7?'星期日':''  
        }
 console.log(previewWeek(6)); // 星期六

2.数组+索引优化代码

 function previewWeek(i) {
      return i > 0 && i < 8 ? '星期' + ['一', '二', '三', '四', '五', '六', '日'][i - 1] : ''
 }
 console.log(previewWeek(6)); // 星期六

2. includes 优化代码

includes 是 ES7 新增的API,与 indexOf 不同的是 includes 直接返回的是 Boolean 值,indexOf 则 返回的索引值, 数组和字符串都有 includes 方法,具体可以查看 Array.prototype.includesString.prototype.includes

需求

以 数组的 includes 为例子,字符串的includes类似,实现一个身份认证方法,通过传入身份Id返回对应的验证结果。

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

3.定点优化代码

需求

写个查询元素的方法

三元定点

  • 动态的数据发生的地点,针对性的优化
function getElement(selector,isAll = false){
    return document[ 'querySelector'+(isAll?'All':'') ](selector)
}
  • 不难发现,动态的数据发生在[]里面的小括号里面,通过定点优化进一步减少了我们的代码量,此种衍生的版本比较多

例如:为 container 类元素根据isShow来显示隐藏

// jQuery 中是否经常这么干?
$('.container')[ isShow?'show' : 'hide' ]()

4. switch语句优化

示例:

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()

5.默认值优化

优化前

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
}

6. 单个 if 语句优化策略

&&

// 示例1:
function log(){
    console.log('前面的flag为真,就会看到我')
}
let flag = true
flag && log();

// 示例2:
if(a && b){
    c()
}
//=> 优化后 a && b && c()
//其他类推

7.多个 if不同条件 执行相同逻辑 优化策略

  • 此种策略采用 归并达到相同结果的 不同条件,从而进行了优化
if(a==1 || b==2 || c==3){
    return "结果"
}

//也可以简写成
if(a==1 || b==2 || c==3)return "结果"

8.单个普通if else优化策略

优化前

let flag = true
if(flag){
    //执行业务逻辑
}else{
    return;
}

优化后

  • 排非策略,此种策略优先排除false情形,通过则后面执行 true 情形的 业务逻辑
let flag = true

if(!flag)return;
//执行业务逻辑

9.单个 if else 执行不同方法 优化策略

  • demo 方法传true执行 success 方法,传 false 执行 error 方法
// 最常用的
function demo(flag){
    flag?success():fail()
}

补充一个不常见的

  • 此种优化策略,结合了布尔值的false和true是可以转成 0 和1,因此可以拿来当索引使用
// 如果你不能保证 你所传的参数一定是布尔值的话 用这种
function demo(flag){
    [false,true].includes(flag) && [fail,success][Number(flag)]()
}

// false 转成 0 ,对应执行success ,true 转成 1,对应执行 fail

// 如果你能保证 你所传的参数一定是布尔值的话 用这种
function demo(flag){
    [fail,success][Number(flag)]()
}

10.多个 else-if 执行不同方法 优化策略

  • 做个权限按钮,不同角色登录一个系统,点击同个按钮执行不同的业务逻辑

优化前

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] )

11.多个 if 嵌套优化策略

  • 有些时候,后端返回的数据里动态存在某个值,也就意味着,有时候有这个数据,有时候没有,然后甩你一句话,“有就显示,没有就不显示”,作为前端的我们自然很严谨。

  • 场景:后端大哥说了,给你返回的数据里面的 如果有 userInfo字段,并且userInfo下面有hobby字段并且有值就显示 hobby里面的内容,否则页面 hobby这一块不显示。

  • 模拟后端返回的数据

let result = {
    status:200,
    codeMsg:'success',
    data:{
        userInfo:{
            age:18,
            hobby:['敲代码','打篮球']
        }
    }
}

优化写法

  • 采用 try catch 策略,此种适合,严谨但又懒的前端
//成功拿到数据了 result
try {
   if(result.data.userInfo.hobby.length){
       //遍历 result.data.userInfo.hobby 进行渲染显示
   }
} catch (error) {
   
}
  • optional chaining优化,新特性
let res = obj?.data?.list?.length <=等价=> let res = obj && obj.data && obj.data.list && obj.data.list.length

作用: 判断这个对象(obj)下的(data)下的(list)下的(length)是否为null,当其中一链为null或者undefined时就返回undefined,这样即使中间缺少一个属性也不会报错,双问号后面接的就是默认值。

let obj ={} 
console.log(obj?.a?.b ?? 233 ) //233 
let obj={a:{b:1}} 
console.log(obj?.a?.b??233) //1
if(result?.data?.userInfo?.hobby?.length){
    //遍历 result.data.userInfo.hobby 进行渲染显示
}

12.模板字符串

对于拼接字符串很实用,可以更加友好。

// 优化前
const welcome = "Hi " + test1 + " " + test2 + ".";
// 优化后
const welcome = `Hi ${test1} ${test2}`;
复制代码

多行字符串的拼接。

// 优化前
const data =
    "abc abc abc abc abc abc\n\t" + "test test,test test test test\n\t";
// 优化后
const data = `abc abc abc abc abc abc
         test test,test test test test`;

13.其他

  • 尽量使用箭头函数
  • 尽量使用模板字符串
  • 尽量使用解构赋值
  • 尽量使用ES6语法,会发现代码会少很多

场景:  

利用ES6剩余参数...取你所想取的数据

// 包含参数对象b和d
const params = {
    a:1,
    b:2,
    c:3,
    d:4
}
// 1
const {a,c} = params
const param = {a,c}
console.log(param); //{a: 1, c: 3}

// 2
const {b,d,...param} = params // b和d字段是你需求排除的字段
console.log(param); //{a: 1, c: 3}

数组剩余参数...的巧用

const arr = [1,2,3,4,5]
const [a,b,...param] = arr // 排除 a和b对应的索引的值(即1和2) ,但是不能随心所欲的排除,比如排除 1和5 取[2,3,4]
param //[3,4,5]
// 如果想排除 1和5 取[2,3,4] 也是有方法的
arr.filter(i=>![1,5].includes(i)) // [2,3,4]