JavaScript 判断优雅写法
最编程
2024-01-17 14:47:38
...
前言
- 在日常的业务开发过程中,避免不了会有对同一值或多个值判断去显示或执行其他逻辑的代码,对于不同的情况我们可以选择不同的判断语句去写对应的逻辑,但是怎么选择使用哪一个判断语句或其他写法,可以使代码的更优雅或更具有可读性呢?
仅两种可能
- 当判断的结果非此即彼(及仅有两种可能)时,我们一般都会选择
if else
这种判断语句。
// if else
if(name === 'detanx') { ... }
else { ... }
三元
- 其实当存在单语句、赋值等情况时,我们还可以选择三元运算语句。
// 三元
let isMaster = false;
isMaster = name === 'detanx' ? true : false;
- 上述使用三元语句改写后,代码数量减少了,相对更优雅一些,可读性相对于
if else
也差不多。 - 在使用三元语句时,不建议再嵌套三元运算。 例如:
let masterStatus = 0; // 0 super, 1 master, 2 normal
let master = 'detanx';
masterStatus = master === 'detanx' ? 0 : (master === '17' ? 1 : 2);
||
、&&
- 除了三元以外,对某些特定情况,我们还可以使用
||
、&&
运算符。例如请求数据结果:
// ||
let responseData = [];
request(res => {
if(res.code === 200) {
responseData = res.data || []; // res.data 是否存在,和后端约定 null/Array
}
})
responseData && responseData.map(item => { // 判断 responseData
// item ...
})
??
- 当且仅当运算符左侧为
null
或undefined
时,选择右侧的值。
let name = '';
const isNullOrUndefined = null;
name = isNullOrUndefined ?? 'default';
多种可能
- 当提到多种可能时,大家首先想到的可能是
if...else if...else
或者switch...case
。例如判断不同的事件:
- 多种可能对应同一种情况
if(status === 0 || status === 1 || status === 2 || status === 3) {
console.log('按钮可以点击');
}
// =>
if([0, 1, 2, 3].includes(status)) {
console.log('按钮可以点击');
}
- 多种可能对应不同情况
- 对应不同的事件,需要有不同的行为和执行逻辑。
let content = [];
if(event === 'click') {
content = ['jump', clickFunction];
} else if (event === 'blur') {
content = ['jungle', blurFunction];
} else if (event === 'scroll') {
content = ['scroll', scrollFunction];
} else if (event === 'size') {
content = ['change', sizeFunction];
} else if (event === 'focus') {
content = ['jungle', focusFunction];
} else {
content = ['other', otherFunction];
}
- 使用对象数据结构改写上述代码。
let content = [];
const eventObject = {
'click': ['jump', clickFunction],
'blur': ['jungle', blurFunction],
'scroll': ['scroll', scrollFunction],
'size': ['change', sizeFunction],
'focus': ['jungle', focusFunction],
}
content = eventObject[event] || ['other', otherFunction];
- 根据我们业务的实际情况,我们也可以灵活的替换其他数据结构,在业务中有很多需要根据某一个值去显示不同的文案等。例如通过判断状态值(
status
)显示当前课程的状态。
// status 0 已删除 1 未开始 2 上课中 3 已下课 4 已评估
let text = '';
if...else
if(status === 0) {
text = '已删除'
} else if (status === 1) {
text = '未开始'
} else if (status === 2) {
text = '上课中'
} else if (status === 3) {
text = '已下课'
} else if (status === 4) {
text = '已评估'
} else {
text = '--'
}
switch...case
switch(status) {
case 0:
text = '已删除';
break;
case 1:
text = '未开始';
break;
case 2:
text = '上课中';
break;
case 3:
text = '已下课';
break;
case 4:
text = '已评估';
break;
default:
text = '--';
break;
}
- 有上面两种写法,可读性是不错,就是写的很冗余,有没有更简洁的写法呢?往下看:
const statusTextArray = ['已删除', '未开始', '上课中', '已下课', '已评估'];
text = statusTextArray[status] || '--';
- 两行代码就搞定了,是不是简洁了非常之多(非连续数值的情况下,我们只需要将对应下标置为
null
或undefined
即可,如果数值过大,不建议使用上面的写法),这就是我们灵活运用了数组的特性和我们数据的特性。有人肯定会说了,你这个只适用数值的情况,不是数值或数值过大的情况又怎么办呢?别急,接着往下看:
// status 非数值或数值过大
const statusTextObject = {
100: '已删除',
101: '未开始',
102: '上课中',
103: '已下课',
104: '已评估'
}
text = statusTextObject[status] || '--';
// 非数值我们将对象的 key 替换为对应status的值即可。
- 多值对应多种情况
- 在日常开发过程中,我们可能需要通过不止判断一个值去做显示或其他逻辑操作,可能需要判断
2
个甚至2
个以上的值,那是否就只能写if...else
了呢?
// limit 权限,status 状态
if (limit === 'super') {
if(status === 0) { // do ... }
else if (status === 1) { // do ... }
else if (status === 2) { // do ... }
else if (status === 3) { // do ... }
else if (status === 4) { // do ... }
} else if (limit === 'normal') {
if(status === 0) { // do ... }
else if (status === 1) { // do ... }
else if (status === 2) { // do ... }
else if (status === 3) { // do ... }
else if (status === 4) { // do ... }
} else {
// do ...
}
- 当情况过多时,嵌套越来越深,代码离优雅就越远,可读性也越差。
// 改写
const limitStatusObject = {
'super-0': () => { // do ... },
'super-1': () => { // do ... },
// ...
'normal-0': () => { // do ... },
'normal-1': () => { // do ... },
// ...
}
// 还可以将每个对应的逻辑单独抽出来
const limitStatusObject = {
'super-0': super0Function,
'super-1': super1Function,
// ...
'normal-0': normal0Function,
'normal-1': normal1Function,
// ...
}
limitStatusObject[`${limit}-${status}`].call(this);
- 出了使用
Object
之外,我们还可以使用ES6
中的Map
数据结构,将对应值的键值组合成对象。
const limitStatusMap = new Map([
[{limit: 'super',status: 0},()=>{ // do ... }],
[{limit: 'super',status: 1},()=>{ // do ... }],
// ...
[{limit: 'normal',status: 0},()=>{ // do ... }],
[{limit: 'normal',status: 1},()=>{ // do ... }],
// ...
]);
const list = [...limitStatusMap].filter(([key,value]) => (key.limit === limit && key.status === status));
list.forEach(([key,value]) => value.call(this));
- 当同一权限下,有几种状态值操作都是相同的,那我们又该怎么写呢?
const functionA = () => { // do ... }
const functionB = ()=> { // do ... }
const limitStatusMap = new Map([
[/^limit_[1-4]$/,functionA],
[/^limit_5$/,functionB],
//...
])
const list = [...actions].filter(([key,value]) => (key.test(`${limit}_${status}`)))
list.forEach(([key,value]) => value.call(this))
- 可以通过使用正则表达式去匹配相同操作的状态值。
深处嵌套对象
- 开发过程中,避免不了会遇到深层对象的取值,既然是深层对象,那我们肯定需要一层一层去判断是否存在对应的key才能继续获取下一层,不然的话,如果某一次数据的某一层不为对象或对应的值不存在时,又没有做异常处理,那我们的程序就会崩溃。显示环境出现这种问题,肯定是大事故了,那你可能就要被炒鱿鱼????了。那我们怎么怎么避免这种问题,并写出优雅的代码呢?
- 正常写法
const user = {
base: {
family: {
parent: {
mather: {
name: '...'
},
father: {
name: '...'
}
}
}
}
}
let fatherName = '';
if(user && user.base && user.base.family && user.base.family.parent && user.base.family.parent.father) {
fatherName = user.base.family.parent.father.name || '-';
}
- 如上所示,当对象层级过深,我们需要每级都判断,那我们还可以怎么写呢?
// 使用 ES6 新特性 ?.
let fatherName = '';
fatherName = user?.base?.family?.parent?.father?.name;
应用案例
- 在项目开发中,我们可能会遇到
tab
选择列表,根据不同的tab
项,请求不同的接口数据,这种情况下,我们不可能每一个请求都写一个单独的函数。 -
tips
:tab
项存在很多3
个及以上,tab
项有多个存在相同的参数,结果处理类似。
// 全部、作业、通知、考勤、口语
let active = 0; // 当前显示 tab 0 - 4
const comment = [ allList, homeworkList, noticeList, newCommentList, spokenList];
getShowList(active);
// 一般情况下,全部 tab的参数不一样,所以我们单独处理
const comment = [ undefined, homeworkList, noticeList, newCommentList, spokenList];
if(active === 0) {
getAllList();
}
getShowList(active);
cosnt getAllList = () => { // request ... }
cosnt getShowList = () => { // request ... }
- 通过使用一个数组,我们可以省去多个请求方法的代码实现,代码复用,但可读性稍低,所以我们最好加上注释。
参考链接
- JavaScript 复杂判断的更优雅写法
往期精彩
- 从0搭建Vite + Vue3 + Element-Plus + Vue-Router + ESLint + husky + lint-staged
- 「前端进阶」JavaScript手写方法/使用技巧自查
- JavaScript设计模式之简介及创建型模式
- 公众号打开小程序最佳解决方案(Vue)
- Axios你可能不知道使用方式
「点赞、收藏和评论」
❤️关注+点赞+收藏+评论+转发❤️,创作不易,鼓励笔者创作更好的文章,谢谢????大家。