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
}
左移运算符 (<<) 将第一个操作数左移指定位数。向左移动的多余位被丢弃。零位从右侧移入。
例如:
按照上面的方法定义好枚举后,我们可以这样使用:
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)
温馨提示:| 是按位或运算符,它在每个操作数的对应位为 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 时,它们看起来像这样:
我们定义的枚举变量只有一个二进制格式的1,并且占据不同的位置。
当我们向技能添加枚举选项时,我们使用skills | skill。假设现在我们需要添加的技能是SKILLS.CSS,那么在执行过程中,就是:
我们可以发现,在技能中,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]
以下是jsbench.me 的性能测试:
使用按位枚举,性能明显更高。
我是从 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
第一次看这段代码,有点迷茫,但总算弄明白了。希望这个技巧能帮到你。谢谢阅读。
翻译来源:https://betterprogramming.pub/the-most-efficient-way-to-write-enumerations-in-javascript-a1b9f41ea651
用for...in循环和Object.keys方法都可以获取对象的属性,那么它们有什么区别呢?getOwnPropertyNames方法输出的结果中还包含了对象的不可枚举属性,可以通过Object.propertyIsEnumerable来判断属性是否可枚举从而对结果进行过滤
在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。
题目:在1,2,3,4,5 五个数中,我们随机选取 3个数。问有多少种取法?并且把每种取出数的方法列举出来。乍看这道题,其实感觉没什么难度。三个for循环不就解决问题了。
数字类型枚举:常规枚举的值都是数字类型,因此被称为数字类型枚举;改变与数字枚举关联的数字:默认情况下,第一个枚举值是 0,后续的值会递增。
枚举是对JavaScript标准数据类型集的扩充,常被用来限定在一定范围内取值的场景。在TypeScript中支持数字和字符串的枚举。我们可以用enum来实现。字符串枚举中没有自增的特性,我们在初始化的时候必须给每一个成员都设字符串。
在当前的javascript中,并没有枚举这个概念,在某些场景中使用枚举更能保证数据的正确性,减少数据校验过程,下面就介绍一下javascript如何模拟实现枚举效果。
使用枚举类型可以允许我们定义一些带名字的常量,也可以清晰地表达意图或创建一组有区别的用例。在 TypeScript 中,支持数字的和基于字符串的枚举。
枚举是受 TypeScript 支持的数据类型。枚举允许您定义一组命名常量。使用它们可以更轻松地记录意图或创建一组不同的案例。枚举大多数用于面向对象的编程语言(如 Java 和 C#)中
枚举的好处是,我们可以定义一些带名字的常量,而且可以清晰地表达意图或创建一组有区别的用例,TS支持数字的和基于字符串的枚举,首先来看数字枚举
枚举 Enum是在众多语言中都有的一种数据类型,JavaScript中还没有(TypeScript有)。用来表示一些特定类别的常量数据,如性别、学历、方向、账户状态等,项目开发中是很常用的。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!