Практические статьи по оптимизации внешнего кода

внешний интерфейс JavaScript
Практические статьи по оптимизации внешнего кода

Я считаю, что у многих мелких партнеров возникает ощущение, когда они берут на себя чужой б/у код.У одного нет комментариев, у двух нет формата, код сложный, а простая функция реализована в N методах.Вдруг у одного два большие головы Как говорится, хороший код радует глаз, а многословный — неприятно. Лично я также перенял немного информации от других коллег или аутсорсинга или многоручного кода, поэтому я резюмировал следующие методы оптимизации кода.

код оптимизации индекса

Начнем с простого примера:

Спрос - это недельное эхо, передача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выполнить

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?'星期日':''  
}

Такое ощущение, что кода стало намного меньше, можно ли его еще оптимизировать? Не сложно обнаружить, что в коде много повторяющихся кодов (в том числе китайских)

Четвертый метод реализации: код оптимизации массива + индекса

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

Суммировать: Иногда бывает много повторяющихся кодов. Мы можем вывести повторяющиеся коды и наблюдать за оставшимися динамическими значениями. Если мы сможем установить лучшую связь с индексом, мы можем еще больше упростить наш код.

благодарныйCherishXY web前端Добавлено, что вы можете использовать карту, идеи мозгового штурма и, в частности, дополнять методы оптимизации карты.

Пятый метод реализации: код оптимизации карты

function previewWeek(i){
    let weeksMap = new Map([
        [1, '一'],
        [2, '二'],
        [3, '三'],
        [4, '四'],
        [5, '五'],
        [6, '六'],
        [7, '日']
    ]);
    return weeksMap.get(i)?'星期'+weeksMap.get(i):''
}

включает оптимизированный код

includes— это новый API в ES7, такой же, какindexOfразница в томincludesвозвращается напрямуюBooleanстоимость,indexOfЗатем возвращаемое значение индекса, как массив, так и строка, имеютincludesметод см.Array.prototype.includesа такжеString.prototype.includes

Давайте сначала рассмотрим простой пример: с массивомincludesНапример, строкаincludesаналогичный

Давайте реализуем метод аутентификации и вернем соответствующий результат проверки, передав идентификатор идентификатора.

Общая реализация:||

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

Недостатком такого способа записи является то, что при изменении количества идентификаторов, которые необходимо проверить, увеличивается количество повторяющегося кода.

Реализация первичной оптимизации:включает в себя

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

Таким образом, когда нужно проверить больше идентификаторов, вам нужно только продолжить добавлять их в массив перед включением.Недостатком является то, что он по-прежнему занимает 4 строки.

окончательная оптимизация: включает + троичный

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

оптимизация оператора 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();
}

Оптимизируемой частью является переключатель

Мы используем форму объекта, чтобы установить отношения сопоставления ключ-значение.


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
}

Стратегия оптимизации одного оператора if

До оптимизации

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()
//其他类推

Этот тип письма часто используется в проектах

Несколько ifs с разными условиями выполняют одну и ту же стратегию логической оптимизации.

До оптимизации

if(a==1){
    return "结果"
}
if(b==2){
    return "结果"
}
if(c==3){
    return "结果"
}

Оптимизировано

if(a==1 || b==2 || c==3){
    return "结果"
}

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

Эта стратегия оптимизируется путем объединения различных условий для достижения одного и того же результата.

Единая общая стратегия оптимизации if else

До оптимизации

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

Оптимизировано

let flag = true

if(!flag)return;

//执行业务逻辑

Стратегия неисключения, эта стратегия предпочтительно исключает ложный случай, а затем выполняет бизнес-логику истинного случая позже.

Single if else с возвращаемым значением Стратегия оптимизации

До оптимизации

function demo(flag){
    if(flag){
        return "真"
    }else{
        return "假"
    }
}

Оптимизировано

function demo(flag){
    return flag? "真" : "假"
}

Один if else выполняет разные методы Стратегии оптимизации

Начнем с примера: демо-метод passtrueвоплощать в жизнь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] || "未知"
}

Несколько 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] )

После оптимизации вам нужно поддерживать только один объект

Несколько вложенных стратегий оптимизации

Иногда в данных, возвращаемых бэкендом, есть определенное значение динамически, а это значит, что иногда эти данные есть, иногда нет, и тогда я оставлю вам предложение: «отображать, если есть, а не отображать». если его не существует", как передняя часть Мы, естественно, строгие

Сценарий: старший брат серверной части сказал, есть ли какие-либо данные в возвращаемых данных для вас.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 Стратегия

Четвертый оптимизированный способ письма

благодарныйliubiantaolv-1 爱乐奇Этот пример добавлен по предложению друга. Заинтересованные друзья могут пойти и посмотреть эту функцию.

Необязательная оптимизация цепочек, новые функции, последнюю версию Google Chrome уже можно испытать, и ее следует добавить позже.ECMAScriptидти стандартно

if(result?.data?.userInfo?.hobby?.length){
    //遍历 result.data.userInfo.hobby 进行渲染显示
}

разное


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('')
  • Используйте стрелочные функции, когда это возможно
  • По возможности используйте строки шаблона
  • Используйте деструктурирующие присваивания, когда это возможно
  • Попробуйте использовать синтаксис ES6, вы обнаружите, что код будет намного меньше.

Пополнить

Оптимизация события привязки DOM, нажмите на дом в следующем примере, чтобы открыть соответствующий номер (тип)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>优化</title>
</head>
<body>
    <div>
        <div class="wrap"><button class="btn" onclick="fn(1)">type=1</button></div>
        <div class="wrap"><button class="btn" onclick="fn(2)">type=2</button></div>
        <div class="wrap"><button class="btn" onclick="fn(3)">type=3</button></div>
    </div>
</body>
<script>
    let btns = document.querySelectorAll('.btn');
    let fn = function(type){
        alert(type)
    }
</script>
</html>

Что, если мы не хотим привязывать события напрямую к dom?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>优化</title>
</head>
<body>
    <div>
        <div class="wrap"><button class="btn">type=1</button></div>
        <div class="wrap"><button class="btn">type=2</button></div>
        <div class="wrap"><button class="btn">type=3</button></div>
    </div>
</body>
<script>
    let btns = document.querySelectorAll('.btn');
    let fn = function(type){
        alert(type)
    }
    btns[0].onclick = fn.bind(null,1)
    btns[1].onclick = fn.bind(null,2)
    btns[2].onclick = fn.bind(null,3)
</script>
</html>

Используйте bind, чтобы изменить эту точку (первый параметр может быть передан null без изменения, а параметры могут быть переданы позже), и он не будет выполнен сразу

2021/12/25 Дополнение

Сцены:Использовать остаточные параметры ES6...Получите нужные данные

// 包含后端不需要字段的参数对象 b和d
const params = {
    a:1,
    b:2,
    c:3,
    d:4
}
// 后端大哥说了,我只要a字段和c字段,其他多余字段给我后端,会报错,于是你就重新组装
// 没有级别的组装
delete params.b
delete params.d

// 青铜级别组装
const param = {
    a:params.a,
    c:params.c
}

// 钻石级别组装
const {a,c} = params
const param = {a,c}

// 王者级别组装
const {b,d,...param} = params // b和d字段是你需求排除的字段
// params:{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]

Эпилог

Если у вас есть лучшие идеи, пожалуйста, оставьте сообщение

Если в тексте есть неточности или ошибки, просьба указать

Прошлые статьи:Практические инструменты и методы во фронтенд-разработке