Skip to main content

重构之对象映射类型

写代码的时候,遇到多重条件分支的时候,使用if else if肯定不如 switch 好用,但 switch 又避免不了 break 语句。但如果只是将数据转化的话,不妨使用对象映射的形式来替换

需求

题型对应的数字转化 将单选 0 多选 1 填空 2 判断 3 简答 4 其他类型-1 转化为 单选 1 多选 2 判断 3 填空 4 简答 5 其他类型-1

目的:前者是其他来源的题目题型标记,而后者是存入数据库的题目标记。

代码

if else if 语句

let ti = {
title: '题目',
answer: '答案',
type: null,
};

let type = 0;
if (type === 0) {
ti.type = 1;
} else if (type === 1) {
ti.type = 2;
} else if (type === 2) {
ti.type = 3;
} else if (type === 3) {
ti.type = 4;
} else if (type === 4) {
ti.type = 5;
} else {
ti.type = -1;
}

console.log(ti.type); // 1

swtich 语句

let ti = {
title: '题目',
answer: '答案',
type: null,
};

let type = 0;
switch (type) {
case 0:
ti.type = 1;
break;
case 1:
ti.type = 2;
break;
case 2:
ti.type = 3;
break;
case 3:
ti.type = 4;
break;
case 4:
ti.type = 5;
break;
default:
ti.type = -1;
break;
}

console.log(ti.type); // 1

显而易见 上面的代码写的很臃肿,并且可读性很差,万一这时候有道题型对应数字的发生了改变,就很容易改错。

不妨定义一个对象,用于映射不同的题目题型,像下面这样

let ti = {
title: '题目',
answer: '答案',
type: null,
};

let type = 0;

const typeMap = {
0: 1, // 单选
1: 2, // 多选
2: 3, // 判断
3: 4, // 填空
4: 5, // 简答
};

ti.type = typeMap[type] ?? -1; // typeMap[type]为0的话 为假值 使用||将会赋值为-1

console.log(ti.type); // 1

像这样的例子还有状态映射。

let status = 1
const statusMap = {
0: '未使用'
1: '已使用',
}
let statusStr = statusMap[status]

这样已经很好了,这里的 1 2 3 4 5 后都添加了注释,增加了一定的可读性,但是还不够,有时候在引用的话或记混了都有可能把填空题判断成简答题,比如后续使用的代码

switch (ti.type) {
case 1: // 单选
// ...
break;
case 2: // 多选
// ...
break;
case 3: // 判断
// ...
break;
case 4: // 填空
// ...
break;
case 5: // 简答
// ...
break;
default:
break;
}

又需要加一遍注释,如果不看typeMap的话,就很大的可能会写错。于是一个好的命名就至关重要了

enum(枚举)

如果使用的是 Typescript,那么可以直接使用 enum(枚举)

enum Qtype {
RADIO = 0,
MULT = 1,
BLANK = 2,
JUDGE = 3,
SHORT = 4,
UNKNOWN = -1,
}

此时的整个代码就可以写成这样

let ti = {
title: '题目',
answer: '答案',
type: null,
};

let type = 0;
const typeMap = {
0: Qtype.RADIO, // 单选
1: Qtype.CHECK, // 多选
2: Qtype.JUDGE, // 判断
3: Qtype.BLANK, // 填空
4: Qtype.SHORT, // 简答
};

ti.type = typeMap[type] ?? Qtype.UNKNOWN;
console.log(ti.type); // 1

switch (ti.type) {
case Qtype.RADIO:
// ...
break;
case Qtype.CHECK: // 多选
// ...
break;
case Qtype.JUDGE: // 判断
// ...
break;
case Qtype.BLANK: // 填空
// ...
break;
case Qtype.SHORT: // 简答
// ...
break;
default:
break;
}

如果不新建一个typeMap变量,还可以直接这样操作

ti.type = {
0: Qtype.RADIO, // 单选
1: Qtype.CHECK, // 多选
2: Qtype.JUDGE, // 判断
3: Qtype.BLANK, // 填空
4: Qtype.SHORT, // 简答
}[type] ?? Qtype.UNKNOWN;

后续重构

如果这时候需求发生了变化,比如判断题与填空题的数字要交换一下,那么也只需要修改Qtype,极大的提高了开发的效率与 bug 的发生。