持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
枚举,其实它就是一个对象,只不过我感觉他又有点像Map,就是存的键值对(一一对应那种),但是它又比Map多了一些其他的特性...
枚举的定义与作用
在TS中,枚举的定义就是很简单的,使用一个关键字——enum。
enum Days {
one,
two,
three,
four
}
这样我们定义好了一个枚举了。那么枚举定义好有什么用呢?那就得谈谈枚举的特性了:(我们来获取刚才使用的枚举)
...
let day = Days['one'];
console.log(day); //0
let key = Days[0];
console.log(key); //one
我们发现我们的day居然有一个初始值,为0。这是为啥呢?我们来看一下它编译为JS后的代码:
{
var Days = void 0;
(function (Days) {
Days[Days["one"] = 0] = "one";
Days[Days["two"] = 1] = "two";
Days[Days["three"] = 2] = "three";
Days[Days["four"] = 3] = "four";
})(Days || (Days = {}));
}
我们发现它还真是一个对象,然后通过给这个对象赋值的形式,让这个对象有一种类似双层映射的感觉。其实它内部就是:
{
'0': 'one',
'1': 'two',
'2': 'three',
'3': 'four',
one: 0,
two: 1,
three: 2,
four: 3
}
不过从中我们也看出来了一个特性:那就是枚举默认就将第一个属性赋值为0,然后后面的属性依次在前一个的属性的值的基础上加1。
自定义值
但是枚举除了会自己加值以外,我们也可以自己定义值:
enum Days {
one=1,
two,
three,
four
}
这时候one=1,two就等于2了,three就等于3,four就等于4。
enum Days {
one=1,
two,
three=6,
four
}
那么这时候他们又等于多少呢?答案是:
{
'1': 'one',
'2': 'two',
'6': 'three',
'7': 'four',
one: 1,
two: 2,
three: 6,
four: 7
}
所以得出结论:只要在定义枚举时,没有给他赋值的,就会以它上一个为基准进行值+1。但是如果定义重了怎么办?那么这时候虽然不会报错,但是会造成双向映射出现问题:
enum Days {
one=3,
two=2,
three,
four
}
console.log(Days);
---------------------------
{
'2': 'two',
'3': 'three',
'4': 'four',
one: 3,
two: 2,
three: 3,
four: 4
}
我们发现这时候one虽然指向3,但是3指向的是three了。所以最好不要搞重复了。
枚举的值为字符串
最后,枚举的值不一定是number类型,它也可以是字符串。
enum Days {
one='一',
two,
three,
four
}
注意这样是不行的,会报错:Enum member must have initializer.我们如果需要枚举的值不用number类型,那么就必须满足以下几个条件之一:
- 要么全部给他赋值
- 要么在不复制的第一个给一个number常量
- 付其他值的在最后一个
enum Days {
one='一',
two=2,
three,
four
}
-------或者----------------
enum Days {
one='一',
two='二',
three='三',
four='四'
}
-------或者----------------
enum Days {
one,
two,
three,
four='四'
}
-------或者----------------
enum Days {
one='一',
two=2,
three,
four
}
但是我们需要注意的是:如果我们赋其他类型的值时,就失去了双向映射了,我们可以来看一下编译后的代码:
var Days = void 0;
(function (Days) {
Days["one"] = "\u4E00";
Days["two"] = "\u4E8C";
Days["three"] = "\u4E09";
Days["four"] = "\u56DB";
})(Days || (Days = {}));
console.log(Days);
}
-------------------------
{ one: '一', two: '二', three: '三', four: '四' }
也就是说我们不能通过Days['一']来反向获取值了。双向映射只能在数字枚举中存在。
常量枚举
最后,还有一种枚举叫常量枚举,它和普通枚举的区别在定义上就是多了个const关键字:
const enum Days {
one='一',
two='二',
three='三',
four='四'
}
但是它是有区别的,因为我们普通定义的枚举,它编译后是存在JS代码的,但是常量枚举编译后是没有JS代码的,它只会将使用这个枚举的地方给替换掉:
const enum Days {
one='一',
two='二',
three='三',
four='四'
}
console.log(Days['one'] === '一');
--------------------------------------
console.log("\u4E00" /* Days['one'] */ === '一');
我们可以发现最后就只有一行输出语句,而且把Days['one']给替换为了一。