当前位置: 首页 > article >正文

JavaScript创建枚举

 相比直接写数字与字符串值,用枚举表示预定义范围的常量值有很多优点,这里就不做赘述了,但目前为止javascript并没有提供原生的enum类型(typescript当然就支持),通常javascript会借助对象类型来等效实现enum类型,实现方式有多种,这里介绍基于代理的枚举实现方式:

(其它实现方式及优缺点详见: https://zhuanlan.zhihu.com/p/629573201在JavaScript中4种创建枚举方式)

基于代理的枚举

代理枚举是一种有趣的实现方式。一个代理对象是一个特殊的对象,它包装另一个对象并修改对原始对象的操作的行为。代理不会改变原始对象的结构。

枚举代理拦截枚举对象的读取和写入操作,并且:

  • 当访问不存在的枚举值时抛出错误
  • 当更改枚举对象属性时抛出错误

代理的get()方法拦截读操作,并在属性名称不存在时抛出错误。set()方法拦截写操作并抛出错误。它旨在保护枚举对象免受写操作的影响。

//enum.js:

//说明:早期的浏览器或某些IE版本可能不支持Proxy(虽然IE已退出舞台,但考虑一些还需要IE的旧项目场景), 这里尽量做下兼容实现:

(function (global) {
    if (!!Proxy) {
        global.Enum = function(baseEnum) {
            return new Proxy(baseEnum, {
                get(target, name) {
                    if (!baseEnum.hasOwnProperty(name) && !name.toString() === 'Symbol(Symbol.toStringTag)') {
                        throw new Error(`"${name}" value does not exist in the enum`)
                    }
                    return baseEnum[name]
                },
                set(target, name, value) {
                    throw new Error('Cannot add a new value to the enum')
                }
            })
        };        
    } else {
        global.Enum = function(baseEnum) {
            //return baseEnum;

            var newEnum = Object.assign({}, baseEnum);            
            Object.defineProperties(newEnum
                , Object.assign({}
                    , ...Object.keys(newEnum).map(function (key) {
                        return {
                            [key]: {
                                get: function () {
                                    //if (!newEnum.hasOwnProperty(key) && !key.toString() === 'Symbol(Symbol.toStringTag)') {
                                    //    throw new Error(`"${key}" value does not exist in the enum`)
                                    //}
                                    return baseEnum[key]    //注意这里不可newEnum[key]否则会死循环
                                },
                                set: function(value) {
                                    throw new Error('Cannot update the value of the enum')
                                }
                            }
                        }
                    })
                )
            );
            
            //防止新属性被添加到对象中(即防止该对象被扩展),只有当"use strict"时才会报错“Error: Cannot add property XXX, object is not extensible”, 否则只是添加新属性无效但不会报错:
            Object.preventExtensions(newEnum);

            return newEnum;
        };
    }
})(window)

 使用方式:

import { Enum } from './enum'
const Sizes = Enum({
  Small: 'small',
  Medium: 'medium',
  Large: 'large',
})
const mySize = Sizes.Medium
console.log(mySize === Sizes.Medium) // logs true

代理枚举的使用方式和普通对象枚举完全相同

代理枚举的缺点

代理枚举的缺点是始终需要导入 Enum 工厂函数并将枚举对象包装在其中。与使用其他实现方式相比,代理枚举可能会带来一些性能损失。代理枚举涉及使用 JavaScript 的代理特性,这可能会使枚举对象的访问速度稍慢一丢丢。

参考资料:

在JavaScript中4种创建枚举方式 - 知乎


http://www.kler.cn/news/148044.html

相关文章:

  • 解决:javax.websocket.server.ServerContainer not available 报错问题
  • 函数声明与函数表达式
  • uniapp之Vue3配置跨域(代理)
  • [RK-Linux] recovery分区详解(二)
  • harmonyos应用开发者高级认证考试部分答案
  • 配置ssh 免密登录 还是要密码才能登录
  • 二次开发问题汇总【C#】
  • MySQL进阶-InnoDB引擎
  • 全新付费进群系统源码 完整版教程
  • 数字人对本地生活商家的影响和应用
  • 竞赛选题 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测
  • Rust语言入门教程(五) - 流控制语句
  • vue 中 js 金额数字转中文
  • 其利天下技术总监冯建武受邀出席“2023年电子工程师大会”并作主题演讲
  • 【精选】框架初探篇之——MyBatis的CRUD及配置文件
  • Linux - 系统调用(syscall)
  • Qt实现绘制自定义形状
  • ORACLE 多实例监听的配置
  • 接收网络包的过程——从硬件网卡解析到IP层
  • jar包不挂断地运行命令
  • 【电路笔记】-电源电压
  • 时间复杂度和运算
  • lack——主页前后端开发优化(精华:java多线程实现数据插入)
  • 【docker】docker的基础命令
  • 消失的数字,旋转数组(leetcode 一题多解)
  • 力扣 hot100 最小覆盖子串 滑动窗口 字符计数
  • 【沁恒蓝牙mesh】CH58x 将RTC时钟切换为LSE外部低速时钟
  • 中年人怎么发展?持续发展?
  • 牛客 算法 HJ103 Redraiment的走法 golang语言实现
  • 【brpc学习实践九】mbvar及bvar可观测