JavaScript —— Symbol数据类型的延伸之(enum枚举)

Symbol数据类型的延伸之(enum枚举)

导语:Symbol是一种基本数据类型,每个从Symbol()返回的值都是唯一的。一个Symbol的值能作为对象属性的标识符,这是该数据类型仅有的目的。 ---- 《摘自MDN》

敲黑板:唯一的、标识符

这句话值得我们细细咀嚼,我们由上面这句话来展开思考。说到唯一性,我们可以联想到的数据类型有什么?

  1. const常量
  2. TypeScript枚举enum
  3. TypeScript Symbol

下面我们就这三种数据类型展开对比:

上一回我们说了const常量,这回我们来说说同样值得我们讨论的,具有相对唯一性的,enum枚举类型。

一、Enum枚举的数字和字符串枚举

enum枚举类型:
我们知道,JavaScript是没有枚举类型的,只有TypeScript有枚举类型。
使用枚举,我们可以定义一些带名字的常量,可以清晰的表达意图或创建一组有区别的用例。 ---- 《摘自TypeScript官网》

  1. 我们先来看一下数字枚举
enum Direction {
  Up = 1,
  Down,
  Left,
  Right
}

如上,我们定义了一个数字枚举,Up使用初始化为1。其余的成员会从1开始自动增长。换句话说,Direction.Up的值为1Down2Left3Right则为4

我们也可以完全不使用初始化器,结果和上面是等效的:

enum Direction {
  Up,
  Down,
  Left,
  Right
}

使用枚举很简单,通过枚举的属性来访问枚举成员,或是通过枚举的名字来访问枚举类型:

enum Response {
  No = 0,
  Yes = 1
}

function respond(recipient: string, message: Response): void {
  // ...
  console.log(`${recipient} is ${message}`)
}

respond("火星", Response.No) // 火星 is 0

这是最常见的枚举形式,但是会有以下的问题:

  • 对打印不友好,打印出来的数值通常只有一个数字;
  • 类型不安全,枚举值不完全唯一,可以被其他数值干扰;
  • 成员无法检查,无法检查枚举值是否是该类型的成员。

例如:我们可以把上面Yes的值改成0,实际上这是不冲突的。因为数字枚举有自增的能力,如果遇到赋予初始值的枚举成员,就会从这个枚举成员重新开始自增:

enum Response {
  No = 0,
  Yes = 0,
  Default
}
// 如果你访问 No 是 0,访问 Yes 也是 0,其实是不能完全保证其唯一性的
console.log(Response.No) // 0
console.log(Response.Yes) // 0
console.log(Response.Default) // 1

针对上面这些问题,那么我们自然而然的想到了另外一种更有针对性的类型:

  1. 字符串枚举类型

字符串枚举的概念很简单,但是有细微的运行时的差别。在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。

例如我们声明一个字符串枚举:

enum Direction {
  Up = "Up",
  Down = "Down",
  Left = "Left",
  Right = "Right"
}

由于字符串枚举没有自增长行为,字符串枚举可以很好的序列化。换句话说,如果你正在调试并且必须要读一个数字枚举的运行时候的值,这个值通常是很难读的 - 它并不能表达有用的信息
但字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。

简而言之就是使枚举类型更加富有语义化了。

除此之外,还有异构枚举、联合枚举和const枚举,这里不再进行赘述。但无一例外,我们都是想让其具备有等级更高的唯一性。甚至于为了唯一性,我们还可以加上Symbol

enum Direction {
  Up = Symbol('Up'),
  Down = Symbol('Down'),
  Left = Symbol('Left'),
  Right = Symbol('Right')
}

但在日常开发的过程中,我们能百分百确定不会出现下面这种情况吗?

// 首次声明
enum Direction {
  Up = "Up",
  Down = "Down",
  Left = "Left",
  Right = "Right"
}
// 团队其他人声明
enum Direction {
  North = "Up",
  South = "Down",
  West = "Left",
  East = "Right"
}
// 又或者是
enum Position {
  Attitude = Symbol('position'),
  Langtitude = Symbol('position')
}
console.log(Direction.Up) // Up
console.log(Direction.North) // Up
console.log(Position.Attitude) // Symbol(position)
console.log(Position.Langtitude) // Symbol(position)
// 当然,这两者是肯定不等的
console.log(Position.Attitude == Position.Langtitude) // false

二、与 Symbol 分析对比

  1. 唯一性。Symbol总是唯一的,如果不刻意共享(Symbol.for()),但enum枚举类型不是绝对唯一的,反而会受到其他数值或字符串干扰;
  2. 标识符。enum想让枚举更加靠近标识符的概念,有时反而会将数据变得越来越复杂(例如赋值字符串或者Symbol),但又不一定实用。当然这样枚举值也可以作为对象的键值。相反Symbol就不会有这种烦恼;
  3. 日常开发中经常使用 enum 来规避魔数, 让代码更加整洁和规范, 可读性也较高;而Symbol只有仅有的一点作用,作为对象属性的标识符
  4. 介于前三点的分析,Symbol作为标识符的时候,比较单纯一点;而enum枚举类型用处比较广泛,它是有条件作为对象属性的标识符的。但如果仅仅只是需要标识某个对象,未免有点浪费资源了,并不推荐。

三、最后

结论:我们分析完这两者之后,其实已经发现,enum的作用远比Symbol要来的多,同时也具备有标识符的属性。而Symbol非常的单纯,就好比正在上学的学生,一心向学。前者也会学习,但社会技能往往要多得多了。

其实两者并没有太多的可比性,只能说分场景吧。不同的场景下那种数据类型更加契合业务就用哪种。如果你只需要一个标识符,可以考虑使用Symbol;如果你是一个相对来讲比较复杂的业务场景,那么可能需要一个可读性强且用来规避魔数的数据类型,那么枚举将是你的不二之选。

以上就是本篇文章的所有内容,都是本菜鸟的个人理解,有哪里不对的欢迎评论区交流指正~
通篇阅读下来,我想要分享的不是如何解决问题,而是面对问题时自己思考问题的思维。我喜欢发散衍生,举一反三,希望大家会喜欢!
下一篇继续学习TypeScript Symbol类型。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值