Есть два и есть два, есть два и три. Превратите неизвестное в известное и станьте своим собственным знанием
предисловие
Давным-давно я опубликовал статью:[Анализ] Схемы замены if-else и переключения в конкретных сценариях, но сценариев использования if-else не так уж и мало как вышеперечисленных статей, сценариев много, и сегодня я напишу, что можно заменить или оптимизировать в разработкеif-elseместо действия.
Акцент на замену или оптимизацию здесь
if-else, осуществляется по определенному сценарию. Цель состоит в том, чтобы улучшить код в конкретных сценариях и сделать его кратким. Повышение удобочитаемости, ремонтопригодности и возможности повторного использования кода. еслиif-elseИспользуемые сценарии относительно просты или оптимизированы.if-elseТогда это плохо скажется на коде. Не рекомендуется использовать другие решения для замены или оптимизации, не писатьif-elseНе написав, вы не сможете оптимизировать ради оптимизации.
1. Запрос диапазона
Например, нарисуйте диапазон выигрышных номеров, диапазон выигрышных номеров 9-12, 14-18, а затем вам нужно определить, выиграл ли номер в лотерею, логика очень проста для достижения
let num1= 15
let num2= 13
if((num1>=9 && num1<=12)||(num1>=14 && num1<=18)){
// 中奖了
}
if((num2>=9 && num2<=12)||(num2>=14 && num2<=18)){
// 中奖了
}
Это вроде бы не проблема записать, если в будущем спрос изменится, выигрышное число будет не 9-12 или 14-18. Скорее 10-14 или 18-20. Это изменит исходную логику кода
if((num1>=10 && num1<=14)||(num1>=18 && num1<=20)){
// 中奖了
}
Или есть другие требования, например, выигрышный номер 9-12, 14-18, 20-22 или 26-30. Все равно придется менять логику if-else
if((num1>=9 && num1<=12)||(num1>=14 && num<=18)||(num1>=20 && num1<=22)||(num2>=26 && num1<=30)){
// 数字在范围内
}
Теперь вы можете использовать некоторые для инкапсуляции функции, вам нужно инкапсулировать ее только один раз, и если объем будущих требований изменится, вы можете
function handleCheckRange(num, ...ranges){
return ranges.some(item=>num>=item[0]&&num<=item[1])
}
handleCheckRange(num1,[9,12],[14,18]) //true
handleCheckRange(num2,[9,12],[14,18]) //false
handleCheckRange(num2,[10,14],[18,20]) //true
handleCheckRange(num2,[9,12],[14,18],[20,22],[26,30]) //false
1. Некоторые люди могут подумать, что если есть другое требование, условие суждения не >= или , или =? так
handleCheckRangeЕго также необходимо изменить. В этом случае необходимо изменить этот метод при возникновении других условий суждения. Но изменить этот метод несложно, просто инкапсулируйте его напрямую2. Если в условиях оценки слишком много изменений, метод инкапсуляции должен быть совместим с другими условиями оценки.Вы можете обратиться к моим примечаниям:Упражнение 5. Моделирование реализации открытых и закрытых интервалов, здесь обсуждаться не будет.
2. Множественные и условия
Я считаю, что каждый столкнется с проблемами, которые могут иметь комбинацию нескольких состояний.
Например, если есть бонусные баллы за участие в горячих распродажах, статус активности (status), предварительный нагрев (status=1),в ходе выполнения(status=2). тип пользователя(type) также делится на обычных пользователей (type=1) вип пользователь (type=2)
Правила таковы: 1. Участвуйте в активности во время разминки, VIP-пользователи получат 1000 баллов, а обычные пользователи — 700 баллов. 1. Участвуйте в текущей активности, VIP-пользователи получат 800 баллов, а обычные пользователи — 300 баллов.
Это было написано раньше
let status=1
let type=2
if(status===1){
if(type===1){
console.log('普通用户在预售中参与活动,赠送700积分')
}
else if(type===2){
console.log('vip用户在预售中参与活动,赠送1000积分')
}
}
else if(status===2){
if(type===1){
console.log('普通用户在进行中参与活动,赠送300积分')
}
else if(type===2){
console.log('vip用户在进行中参与活动,赠送800积分')
}
}
// 或者
if(status===1&&type===1){
console.log('普通用户在预售中参与活动,赠送700积分')
}
else if(status===1&&type===2){
console.log('vip用户在预售中参与活动,赠送1000积分')
}
else if(status===2&&type===1){
console.log('普通用户在进行中参与活动,赠送300积分')
}
else if(status===2&&type===2){
console.log('vip用户在进行中参与活动,赠送800积分')
}
Но теперь вы можете использовать метод записи obj, так что, если у вас возникнут какие-либо условия для изменения в будущем, просто измените конфигурацию obj напрямую.
let obj={
'status=1&type=1':'普通用户在预售中参与活动,赠送700积分',
'status=1&type=2':'vip用户在预售中参与活动,赠送1000积分',
'status=2&type=1':'普通用户在进行中参与活动,赠送300积分',
'status=2&type=2':'普通用户在进行中参与活动,赠送800积分'
}
console.log(obj[`status=${status}&type=${type}`])
3. Множественное или условие
Например, введите название города и выведите название провинции.
let city='广州'
if(city==='广州'||city==='佛山'){
console.log('广东')
}
else if(city==='海口'||city==='三亚'){
console.log('海南')
}
Недостатком этого является то, что еслиif-elseПо мере увеличения числа код будет увеличиваться, а условия оценки станут очень длинными.Еще одна проблема заключается в том, что стиль может быть неоднородным.
Оптимизируйте другими способами метод первый
let arr=[
{
city:'广州',
province:'广东'
},
{
city:'佛山',
province:'广东'
},
{
city:'海口',
province:'海南'
},
{
city:'三亚',
province:'海南'
}
]
console.log(arr.filter(item=>item.city===city)[0].province)//广东
Способ второй
let city='广州'
let obj={
'广州':'广东',
'佛山':'广东',
'海口':'海南',
'三亚':'海南',
}
console.log(obj[city])// 广东
Увидев, что Гуандун и Хайнань были написаны так много раз, каждый может быть подавлен.В провинции 20 городов, и их нужно написать 20 раз.Некоторые люди могут думать о городах как о городах.key, а затем оценивать входящиеcityВы вkeyВнутри код выглядит следующим образом.
let city='广州'
let obj={
'广州,佛山':'广东',
'海口,三亚':'海南',
}
for(let key in obj){
if(key.includes(city)){
console.log(obj[key])
break
}
}
//广东
Но вылезают и недостатки, т. е. вышеописанный способ имеетbug, выводится только одно слово названия города, а также может быть выведена соответствующая провинция.
let city='州'
let obj={
'广州,佛山':'广东',
'海口,三亚':'海南',
}
for(let key in obj){
if(key.includes(city)){
console.log(obj[key])
break
}
}
//广东
Чтобы решить эту проблему, есть два пути, один из которых состоит в том, чтобы поставитьkeyПреобразуйте в массив, а затем оцените или используйтеMap
// 方式一:把 key 转成数组再判断
let city='广州'
let obj={
'广州,佛山':'广东',
'海口,三亚':'海南',
}
let keys=[]
for(let key in obj){
keys=key.split(',')
if(keys.includes(city)){
console.log(obj[key])
break
}
}
// 方式二:使用Map
let city='广州'
let map=new Map([
[['广州','佛山'],'广东'],
[['海口','三亚'],'海南'],
])
for (let key of map.keys()) {
if(key.includes(city)){
console.log(obj[key])
break
}
}
//广东
4. Неправильное если-иначе, если
В этом случаеif-elseifПравил не найти. Например, необходимо проводить мероприятия по отбору студентов на получение стипендии.
1. Комплексная оценка качества учащихся (quality>=90) 90 или выше, со средним баллом 4,5 или выше, чтобы стать первоклассным кандидатом на получение стипендии.
2. Учащиеся с общим баллом качества 80 или выше (quality>=80), со средним баллом не менее 2,5 по каждому предмету, чтобы стать кандидатом на получение стипендии второго класса.
3. Общий балл качества обучающихся должен быть не ниже 75 (quality>=75), получил другие награды и награды и стал кандидатом на получение стипендии третьего класса.
let studentInfo={
name:'守候',
chinese:4.6,
math:4.7,
english:4,
computer:4.8,
quality:93,
prizes:['搬砖','扫地']
}
let subjectAll=['chinese','math','english','computer']
function handle (student,subject) {
function getAverage(){
let sum=0
subject.forEach(item=>sum+=student[item])
return sum/subject.length
}
function checkScore(){
return subject.every(item => student[item]>2.5)
}
if(student.quality>=90&&getAverage()>4.5){
console.log('成为一等奖学金候选人')
// 其他代码
}
else if(student.quality>=80&&checkScore()){
console.log('成为二等奖学金候选人')
// 其他代码
}
else if(student.quality>=75&&student.prizes.length>0){
console.log('成为三等奖学金候选人')
// 其他代码
}
}
handle(studentInfo,subjectAll) //成为一等奖学金候选人
Код выглядит очень простым и завершенным, но в реальной разработкеif-elseifколичество уровней, каждыйif-elseifЛогика суждения и код, выполняющий внутри нее операцию, выходят далеко за рамки этого примера. ТакhandleКод для этого метода будет длинным, а сам метод станет огромным. Это сильно влияет на удобочитаемость, ремонтопригодность и возможность повторного использования кода. Если требования меняются, необходимо уточнить логику всей функции.
Приведенный выше код в основном нуждается в обработкеif-elseif. но этиif-elseНет правил, которые можно найти, поэтому все можно извлечь только по отдельности, и все они инкапсулированы в функции.
function handle (student,subject) {
function getAverage(){
let sum=0
subject.forEach(item=>sum+=student[item])
return sum/subject.length
}
function checkScore(){
return subject.every(item => student[item]>2.5)
}
let rules=[
{
rule(){
return student.quality>=90&&getAverage()>4.5
},
fn(){
console.log('成为一等奖学金候选人')
// 其他代码
}
},
{
rule(){
return student.quality>=80&&checkScore()
},
fn(){
console.log('成为二等奖学金候选人')
// 其他代码
}
},
{
rule(){
return student.quality>=75&&student.prizes.length>0
},
fn(){
console.log('成为三等奖学金候选人')
// 其他代码
}
}
]
for(let item of rules){
if(item.rule()){
item.fn()
// 执行完函数马上返回,不再执行下一次循环
return
}
}
}
Это пока естьitem.fn()Если он выполнен, значит, студент стал кандидатом, просто верните его.
Таким образом, код также полностью соответствует предыдущемуif-elseifлогика. У некоторых могут возникнуть сомнения, что код не уменьшился, а увеличился, но на самом деле этот код был разбит на куски, а читабельность и ремонтопригодность улучшены, если есть необходимость что-то там изменить, мы тоже не будем нужно возиться со всей функцией, просто изменитьrules.
5. Несколько, если
В другом случае несколькоif-elseсвязанный с исполняемым кодом,
Например, есть страница, которая может отображать следы, записанные пользователем, а также позволяет пользователю выбрать запись собственных следов.Областью записи может быть провинция, город или район. Затем код должен реализовать провинцию и город, связь с несколькими вариантами выбора. Логика такова: если вы выбираете провинцию, вы можете не выбирать город, но если вы выбираете город, вы выбираете провинцию и так далее. Ниже приведен простой псевдокод.
function initPostion(){
//所有省份列表
let provinceList=['广东','广西','海南','....']
//已选省份下辖的所有城市
let cityList=[]
//已选城市下辖的所有区
let districtList=[]
//已选择省份
let selectedProvinces=['广东','广西']
//已选择城市
let selectedCitys=['广州']
//已选择区
let selectedDistricts=['天河区']
//如果选了省份
if (selectedProvinces.length>0) {
//根据 selectedProvinces 获取 cityList 的逻辑
//其他代码
}
if (selectedCitys.length>0) {
//根据 selectedCitys 获取 districtList 的逻辑
//其他代码
}
//其他初始化显示的逻辑
}
Как только псевдокод написан, некоторые разработчики должны были увидеть проблему. всеifВсе они связаны друг с другом, и логика кода в if может быть намного длиннее. Если в дальнейшем спрос изменится, требуется выбрать страну, затем провинцию или город, либо после выбора района можно также выбрать город и деревню. К тому времениifстанет больше,initPostionОбщий код может стать огромным. Обслуживание может быть трудоемким и подверженным ошибкам.
Чтобы решить эту проблему, вы можетеifразделить на функции
function initPostion(){
//所有省份列表
let provinceList=['广东','广西','海南','....']
//已选省份下辖的所有城市
let cityList=[]
//已选城市下辖的所有区
let districtList=[]
//已选择省份
let selectedProvinces=['广东','广西']
//已选择城市
let selectedCitys=['广州']
//已选择区
let selectedDistricts=['天河区']
let handleObj={
provinces(){
//如果选了省份
if (selectedProvinces.length>0) {
//根据 selectedProvinces 获取 cityList 的逻辑
//其他代码
}
},
city(){
if (selectedCitys.length>0) {
//根据 selectedCitys 获取 districtList 的逻辑
//其他代码
}
}
}
let handleFns=['provinces','city']
for(let fnName of handleFns){
handleObj[fnName]()
}
//其他初始化显示的逻辑
}
Может показаться, что кода много, но управлять им будет проще, чем исходным решением.ifВсе они разбиты на функции, если вам нужно изменить определенный фрагмент кода, просто измените определенный фрагмент кода, и вам не нужно менять другие коды. Если есть изменение в спросе, это должно изменитьсяhandleObjфункция свойства , иhandleFnsпорядок .
Ссылка на ссылку
[Анализ] Схемы замены if-else и переключения в конкретных сценариях
Более элегантный способ написания сложных суждений в JavaScript
резюме
хорошо, оif-elseНа этом вторая статья о замене и оптимизации схемы . Здесь снова заменить и оптимизироватьif-elseЗаявление, рекомендуется использовать конкретную схему в конкретном сценарии. Помните, что нельзя заменять ради замены, не оптимизировать ради оптимизации.
Если я найду другой выигрыш в будущем, я напишу статью как можно скорее. Если у всех есть какие-либо предложения, мнения или ошибки в статье, пожалуйста, оставьте сообщение в области комментариев для улучшения.
------------------------- Великолепная разделительная линия --------------------
Если вы хотите узнать больше и пообщаться со мной, добавьте меня в WeChat. Или обратите внимание на мой паблик WeChat: В ожидании книжного магазина