本篇文章将讲枚举类型的基础知识,枚举与哈希,集合这三者的区别以及各自合适用的场景。
枚举
枚举常用于定义一些带名字的常量,枚举内的数据项类型可为number或string。
数字枚举
声明数字枚举的语法如下:
// 在没指定首项的值的情况下,默认首的值为0,往后每项加1
enum NumberList {
first, // 0
second, // 1
third, // 2
}
// 在值指定首项的值的情况下,以首项的值为起始值,往后每项加1
enum NumberList {
first = 1, // 1
second, // 2
third, // 3
}
// 使用也很简单,在定函数参数时,把枚举作为参数类型
function log_number(param:NumberList) {
console.log(param);
}
// 传入枚举的某一项
log_number(NumberList.first);
字符串枚举
字符串枚举就是数据项都是string的枚举,它不存在数字枚举的自增长行为,需要每项都赋值
enum Directions {
east = 'east',
south = 'south',
west = 'west',
north = 'north',
}
异构枚举
同时拥有number和string类型的数据项的枚举
enum Mix {
first = 1,
second = 'second',
}
计算值和常量
你可以将一些表达式或常量赋值给枚举的项,ts会在编译过程中算出表达式的结果(结果必须是number或string,否则报错),并赋值给项。
const num = 3;
function get_number() {
return 2;
}
enum ComputedEnum {
first, // 0
second = get_number(), // 2
third = num, // 4
fourth = 1 << 2, // 3
fifth = 'fifth'.length, // 5
}
// 若在非末项使用了表达式,则随后的项得赋值,否则报错
enum NumberList {
first, // 0
second = get_number(), // 2
third, // 报错,值无法推断,得赋一个值
}
// 在字符串枚举中不能使用
enum Mix {
first = '',
second = get_number(), //报错
}
反向映射
枚举编译成es5后,其实就是个对象,保存了“键-值”的映射关系,而创建数字枚举时,数字枚举内还会多生成一个“值-键”的映射。
enum NumberList {
first,
second,
third,
}
以上代码编译成es5后如下所示:
var NumberList;
(function (NumberList) {
NumberList[NumberList["first"] = 0] = "first";
NumberList[NumberList["second"] = 1] = "second";
NumberList[NumberList["third"] = 2] = "third";
})(NumberList || (NumberList = {}));
等价于
var NumberList;
(function (NumberList) {
// 原映射
NumberList["first"] = 0;
NumberList["second"] = 1
NumberList["third"] = 2;
// 反向映射
NumberList[0] = "first";
NumberList[1] = "second";
NumberList[2] = "third";
})(NumberList || (NumberList = {}));
const 枚举
正如上面说的,枚举编译后会生成一个保存映射关系的对象。有时候,为了节省这部分开销,常量枚举在编译的时候,枚举内的变量会被内联到调用方内,而不保留常量枚举。
const enum NumberList {
first,
second,
third,
}
const arr = [NumberList.first, NumberList.second, NumberList.third];
上述的代码编译后,只留下了引用枚举变量的数组
const array = [0 /* first */, 1 /* second */, 2 /* third */];
枚举,哈希,集合
枚举(enum):有键值对(映射数字枚举还有反向映射),不可遍历,声明以后不可修改;
哈希(object和map):有键值对,可遍历,声明后可修改;
集合(set):只有键(或者说只有值也OK),可遍历,声明后可修改;
以上每个数据类型的键都是唯一的。
各自的应用场景
定义一组常量用枚举,不像map和set那样存在被修改的风险。
函数处理过程中产生的中间变量用map,譬如拼接数据:
const user_hash:any= {};
const user_infos = [{user_id:1, name:'one'}, {user_id:2, name:'two'}, {user_id:3, name:'three'}];
const user_class = [{user_id:1, subject:'English'}, {user_id:2, subject:'Math'}, {user_id:3, subject:'Chinese'}];
for (const item of user_infos) {
user_hash[item.user_id] = item;
}
for (const item of user_class) {
const { user_id } = item;
user_hash[user_id] = { ...item, ...user_hash[user_id] };
}
判断数据是否存在某个结果集内,或做去重,用set:
// 预设可选的科目和上课时间
const subject_set = new Set(['English', 'Math']);
const class_day_set = new Set(['Saturday', 'Sunday']);
// 假设这是前端传来的参数
const request_body = {
subject: 'English',
class_day: 'Monday',
};
// 校验参数是否合法
subject_set.has(request_body.class_day); // true
class_day_set.has(request_body.subject); // false
// 用set的key唯一性实现数组去重
const array1 = [1, 2, 3];
const array2 = [3, 4, 5];
const set = new Set(array1.concat(array2));
const array = [...set]; // [1, 2, 3, 4, 5, 6];
网友评论