JavaScript中的四种枚举方式


JavaScript中的四种枚举方式

文章插图
当一个变量有一个来自有限的预定义常量的值时,使用枚举是很方便的 。枚举使你不必使用魔法数字和字符串(这被认为是一种反模式) 。字符串和数字具有无数个值,而其他类型如布尔值则是有限的集合 。
一周的日子(星期一,星期二,...,星期日),一年的季节(冬季,春季,夏季,秋季)和基本方向(北,东,南,西)都是具有有限值集合的例子 。
当一个变量有一个来自有限的预定义常量的值时,使用枚举是很方便的 。枚举使你不必使用魔法数字和字符串(这被认为是一种反模式) 。
让我们看看在JAVAScript中创建枚举的四种好方法(及其优缺点) 。
基于对象的枚举【JavaScript中的四种枚举方式】枚举是一种数据结构,它定义了一个有限的具名常量集 。每个常量都可以通过其名称来访问 。
让我们来考虑一件T恤衫的尺寸:Small,Medium,和Large 。
在JavaScript中创建枚举的一个简单方法(虽然不是最理想的)是使用一个普通的JavaScript对象 。
const Sizes = {Small: 'small',Medium: 'medium',Large: 'large',}const mySize = Sizes.Mediumconsole.log(mySize === Sizes.Medium) // logs trueSizes是一个基于JavaScript对象的枚举,它有三个具名常量:Sizes.Small、Sizes.Medium以及Sizes.Large 。
Sizes也是一个字符串枚举,因为具名常量的值是字符串:'small' ,'medium',以及 'large' 。
要访问具名常量值,请使用属性访问器 。例如,Sizes.Medium的值是'medium' 。
枚举的可读性更强,更明确,并消除了对魔法字符串或数字的使用 。
优缺点普通的对象枚举之所以吸引人,是因为它很简单:只要定义一个带有键和值的对象,枚举就可以了 。
但是在一个大的代码库中,有人可能会意外地修改枚举对象,这将影响应用程序的运行 。
const Sizes = {Small: 'small',Medium: 'medium',Large: 'large',}const size1 = Sizes.Mediumconst size2 = Sizes.Medium = 'foo' // Changed!console.log(size1 === Sizes.Medium) // logs falseSizes.Medium 枚举值被意外地改变 。
size1,虽然被初始化为Sizes.Medium,但不再等同于Sizes.Medium!
普通对象的实现没有受到保护,因此无法避免这种意外的改变 。
让我们仔细看看字符串和symbol枚举 。以及如何冻结枚举对象以避免意外改变的问题 。
枚举值类型除了字符串类型,枚举值可以是一个数字:
const Sizes = {Small: 0,Medium: 1,Large: 2}const mySize = Sizes.Mediumconsole.log(mySize === Sizes.Medium) // logs true上述例子中,Sizes枚举是数值枚举,因为值都是数字:0,1,2 。
你也可以创建symbol枚举:
const Sizes = {Small: Symbol('small'),Medium: Symbol('medium'),Large: Symbol('large')}const mySize = Sizes.Mediumconsole.log(mySize === Sizes.Medium) // logs true使用symbol的好处是,每个symbol都是唯一的 。这意味着,你总是要通过使用枚举本身来比较枚举:
const Sizes = {Small: Symbol('small'),Medium: Symbol('medium'),Large: Symbol('large')}const mySize = Sizes.Mediumconsole.log(mySize === Sizes.Medium)// logs trueconsole.log(mySize === Symbol('medium')) // logs false使用symbol枚举的缺点是JSON.stringify()将symbol字符串化为null、undefined,或者跳过有symbol作为值的属性:
const Sizes = {Small: Symbol('small'),Medium: Symbol('medium'),Large: Symbol('large')}const str1 = JSON.stringify(Sizes.Small)console.log(str1) // logs undefinedconst str2 = JSON.stringify([Sizes.Small])console.log(str2) // logs '[null]'const str3 = JSON.stringify({ size: Sizes.Small })console.log(str3) // logs '{}'在下面的例子中,我将使用字符串枚举 。但是你可以自由地使用你需要的任何值类型 。
如果你可以自由选择枚举值类型,就用字符串吧 。字符串比数字和symbol更容易进行调试 。
基于Object.freeze()枚举保护枚举对象不被修改的一个好方法是冻结它 。当一个对象被冻结时,你不能修改或向该对象添加新的属性 。换句话说,这个对象变成了只读 。
在JavaScript中,Object.freeze()工具函数可以冻结一个对象 。让我们来冻结Sizes枚举:
const Sizes = Object.freeze({Small: 'small',Medium: 'medium',Large: 'large',})const mySize = Sizes.Mediumconsole.log(mySize === Sizes.Medium) // logs trueconst Sizes = Object.freeze({ ... }) 创建一个冻结的对象 。即使被冻结,你也可以自由地访问枚举值: const mySize = Sizes.Medium 。


推荐阅读