JavaScript编写枚举的最有效方法

2022-07-1821:32:35编程语言入门到精通Comments1,024 views字数 2882阅读模式

JavaScript编写枚举的最有效方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

JavaScript 语言本身不支持枚举。如果我们想模拟枚举,我们可以使用一个对象。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

假设有这样一个场景,我们需要统计员工的技术栈,目前我们需要标记的技术有 CSS、JavaScript、HTML、WebGL。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

然后我可以这样写枚举:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

const SKILLS = {
  CSS: 1 ,
  JS: 2,
  HTML: 3,
  WEB_GL: 4
}
复制代码

之前是这样写的,但是,最近看vue源码的时候,发现了一个高效使用枚举的技巧,在这里分享给大家。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

定义枚举文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我们可以这样写上面的枚举:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

const SKILLS = {
  CSS: 1 ,
  JS: 1 << 1,
  HTML: 1 << 2,
  WEB_GL: 1 << 3
}
复制代码

<< 是什么?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

左移运算符 (<<) 将第一个操作数左移指定位数。向左移动的多余位被丢弃。零位从右侧移入。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

  • 二进制的 1 是 0000 0001 ,左移一位是 0000 0010 ,即十进制的 2 。
  • 如果我们将其移动两位,它将变为 0000 0100 ,即十进制的 4。
  • 如果我们将其移动三位,它将变为 0000 1000 ,即十进制的 8。
  • 如果我们将其移动 N 位,它将变为 2^Nin 十进制。

用法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

按照上面的方法定义好枚举后,我们可以这样使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

const SKILLS = {
  CSS1 ,
  JS1 << 1,
  HTML1 << 2,
  WEB_GL1 << 3
}

// Use this value to store a user's tech-stack
let skills = 0

// add a skill for the user
function addSkill(skill) {
  skills = skills | skill
}

addSkill(SKILLS.CSS)
addSkill(SKILLS.JS)

// If this value is not 0, it means that the user has mastered the tech
console.log('Does he know CSS'SKILLS.CSS & skills)
console.log('Does he know JavaScript'SKILLS.JS & skills)
console.log('Does he know Web GL'SKILLS.WEB_GL & skills)
复制代码

JavaScript编写枚举的最有效方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

温馨提示:| 是按位或运算符,它在每个操作数的对应位为 1 的每个位位置返回 1。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

cons
t a = 5;        // 00000000000000000000000000000101
const b = 3;        // 00000000000000000000000000000011
console.log(a | b); // 00000000000000000000000000000111
// expected output: 7
复制代码

如何理解这段代码?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

在 JavaScript 中,整数存储在 4 个字节中,即 32 位。第一个代表正负,后面的31代表数字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

当我们用二进制表示 1 , 1 << 2 时,它们看起来像这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

JavaScript编写枚举的最有效方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我们定义的枚举变量只有一个二进制格式的1,并且占据不同的位置。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

当我们向技能添加枚举选项时,我们使用skills | skill。假设现在我们需要添加的技能是SKILLS.CSS,那么在执行过程中,就是:JavaScript编写枚举的最有效方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

\文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我们可以发现,在技能中,SKILLS.CSS对应的位置会变成1。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

反之,那么我们可以通过查看skills&SKILLS.CSS的结果是否为0来判断技能中是否存在SKILLS.CSS。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

顺便说一句,这里我们也可以发现这个技巧有个缺点,就是枚举项不能超过 31 个。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我们为什么要使用这个技巧?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

答案很简单,这样的代码运行起来更高效。CPU中有直接对应位操作的指令,因此效率更高。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我们也可以做一个性能测试。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

如果我们不使用按位运算,而是使用传统的方法(数组或映射)来实现,那么代码如下。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

Array 方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

const SKILLS = {
  CSS: 1 ,
  JS: 1 << 1,
  HTML: 1 << 2,
  WEB_GL: 1 << 3
}

// Use an array to store the user's tech-stack
let skills = []

function addSkill(skill) {
  if (!skills.includes(skill)) { // Avoid duplicate storage
    skills.push(skill)
  }
}

addSkill(SKILLS.CSS)
addSkill(SKILLS.JS)

skills.includes(SKILLS.CSS)
skills.includes(SKILLS.JS)
skills.includes(SKILLS.WEB_GL)
复制代码

Map 方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

const SKILLS = {
  CSS: 1 ,
  JS: 1 << 1,
  HTML: 1 << 2,
  WEB_GL: 1 << 3
}

// Use a map to store the user's tech-stack
let skills = {}

function addSkill(skill) {
  if (!skills[skill]) {
    skills[skill] = true
  }
}

addSkill(SKILLS.CSS)
addSkill(SKILLS.JS)

skills[SKILLS.CSS]
skills[SKILLS.JS]
skills[SKILLS.WEB_GL]
复制代码

这是 jsbench.me 的性能测试:JavaScript编写枚举的最有效方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

\文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

使用按位枚举,性能明显更高。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

学习Vue源码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

我是从 Vue 源代码中学到的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

export const enum ShapeFlags {
  ELEMENT = 1,
  FUNCTIONAL_COMPONENT = 1 << 1,
  STATEFUL_COMPONENT = 1 << 2,
  TEXT_CHILDREN = 1 << 3,
  ARRAY_CHILDREN = 1 << 4,
  SLOTS_CHILDREN = 1 << 5,
  TELEPORT = 1 << 6,
  SUSPENSE = 1 << 7,
  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
  COMPONENT_KEPT_ALIVE = 1 << 9,
  COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
}
复制代码

地址:github1s.com/vuejs/core/…文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

第一次看这段代码,有点迷茫,但现在总算弄明白了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

作者:陆荣涛
来源:稀土掘金文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/25395.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/25395.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定