千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:重庆千锋IT培训  >  技术干货  >  用JavaScript编写枚举的最有效方法

用JavaScript编写枚举的最有效方法

来源:千锋教育
发布人:lxl
时间: 2023-02-10 15:50:00

      JavaScript 语言本身不支持枚举。如果我们想模拟枚举,我们可以使用一个对象。

  假设有这样一个场景,我们需要统计员工的技术栈,目前我们需要标记的技术有 CSS、JavaScript、HTML、WebGL。

  然后我可以这样写枚举:

  const SKILLS = {

  CSS: 1 ,

  JS: 2,

  HTML: 3,

  WEB_GL: 4

  }

  之前是这样写的,但是,最近看vue源码的时候,发现了一个高效使用枚举的技巧,在这里分享给大家。

  定义枚举

  我们可以这样写上面的枚举:

  const SKILLS = {

  CSS: 1 ,

  JS: 1 << 1,

  HTML: 1 << 2,

  WEB_GL: 1 << 3

  }

  << 是什么?

  左移运算符 (<<) 将第一个操作数左移指定位数。向左移动的多余位被丢弃。零位从右侧移入。

  例如:

  · 二进制的 1 是 0000 0001 ,左移一位是 0000 0010 ,即十进制的 2 。

  · 如果我们将其移动两位,它将变为 0000 0100 ,即十进制的 4。

  · 如果我们将其移动三位,它将变为 0000 1000 ,即十进制的 8。

  · 如果我们将其移动 N 位,它将变为 2^Nin 十进制。

  用法

  按照上面的方法定义好枚举后,我们可以这样使用:

  const SKILLS = {

  CSS: 1 ,

  JS: 1 << 1,

  HTML: 1 << 2,

  WEB_GL: 1 << 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)

  

2

 

  温馨提示:| 是按位或运算符,它在每个操作数的对应位为 1 的每个位位置返回 1。

  cons

  t a = 5; // 00000000000000000000000000000101

  const b = 3; // 00000000000000000000000000000011

  console.log(a | b); // 00000000000000000000000000000111

  // expected output: 7

  如何理解这段代码?

  在 JavaScript 中,整数存储在 4 个字节中,即 32 位。第一个代表正负,后面的31代表数字。

  当我们用二进制表示 1 , 1 << 2 时,它们看起来像这样:

  

3

 

  我们定义的枚举变量只有一个二进制格式的1,并且占据不同的位置。

  当我们向技能添加枚举选项时,我们使用skills | skill。假设现在我们需要添加的技能是SKILLS.CSS,那么在执行过程中,就是:

  

4

 

  我们可以发现,在技能中,SKILLS.CSS对应的位置会变成1。

  反之,那么我们可以通过查看skills&SKILLS.CSS的结果是否为0来判断技能中是否存在SKILLS.CSS。

  顺便说一句,这里我们也可以发现这个技巧有个缺点,就是枚举项不能超过 31 个。

  我们为什么要使用这个技巧?

  答案很简单,这样的代码运行起来更高效。CPU中有直接对应位操作的指令,因此效率更高。

  我们也可以做一个性能测试。

  如果我们不使用按位运算,而是使用传统的方法(数组或映射)来实现,那么代码如下。

  Array 方法:

  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 方法:

  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]

  这是 http://jsbench.me 的性能测试:

  

1

 

  使用按位枚举,性能明显更高。

  学习Vue源码

  我是从 Vue 源代码中学到的。

  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

  }

  地址:https://github1s.com/vuejs/core/blob/HEAD/packages/shared/src/shapeFlags.ts

  第一次看这段代码,有点迷茫,但现在总算弄明白了。

  希望这个技巧能帮到你。

  - End -

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

java的输入语句—— Scanner类

2023-05-04

java数据库操作常识事务的四大特性

2023-05-04

DML数据操作之增加或删除数据

2023-05-04

最新文章NEW

socket是什么?有什么作用?

2023-05-04

Java常量定义是什么

2023-04-28

一分钟带你学多线程

2023-04-28

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>