欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

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 ...
})

??

  • 当且仅当运算符左侧为 nullundefined 时,选择右侧的值。
let name = '';
const isNullOrUndefined = null;
name = isNullOrUndefined ?? 'default';

多种可能

  • 当提到多种可能时,大家首先想到的可能是 if...else if...else 或者 switch...case。例如判断不同的事件:
  1. 多种可能对应同一种情况
if(status === 0 || status === 1 || status === 2 || status === 3) {
    console.log('按钮可以点击');
}
// =>

if([0, 1, 2, 3].includes(status)) {
    console.log('按钮可以点击');
}
  1. 多种可能对应不同情况
  • 对应不同的事件,需要有不同的行为和执行逻辑。
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] || '--';
  • 两行代码就搞定了,是不是简洁了非常之多(非连续数值的情况下,我们只需要将对应下标置为 nullundefined 即可,如果数值过大,不建议使用上面的写法),这就是我们灵活运用了数组的特性和我们数据的特性。有人肯定会说了,你这个只适用数值的情况,不是数值或数值过大的情况又怎么办呢?别急,接着往下看:
// status 非数值或数值过大
const statusTextObject = {
    100: '已删除',
    101: '未开始',
    102: '上课中',
    103: '已下课',
    104: '已评估'
}
text = statusTextObject[status] || '--';

// 非数值我们将对象的 key 替换为对应status的值即可。
  1. 多值对应多种情况
  • 在日常开发过程中,我们可能需要通过不止判断一个值去做显示或其他逻辑操作,可能需要判断 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才能继续获取下一层,不然的话,如果某一次数据的某一层不为对象或对应的值不存在时,又没有做异常处理,那我们的程序就会崩溃。显示环境出现这种问题,肯定是大事故了,那你可能就要被炒鱿鱼????了。那我们怎么怎么避免这种问题,并写出优雅的代码呢?
  1. 正常写法
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 项,请求不同的接口数据,这种情况下,我们不可能每一个请求都写一个单独的函数。
  • tipstab 项存在很多 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你可能不知道使用方式

「点赞、收藏和评论」

❤️关注+点赞+收藏+评论+转发❤️,创作不易,鼓励笔者创作更好的文章,谢谢????大家。