JavaScript中确保枚举定义不被更改的方法

JavaScript中确保枚举定义不被更改的方法

技术背景

在JavaScript里,枚举并不是原生支持的数据类型。不过在实际开发时,我们常常需要定义一组固定的常量,也就是枚举,来提升代码的可读性与可维护性。然而,JavaScript是动态语言,怎样保证枚举定义不被更改,成为了一个关键问题。

实现步骤

1. 使用Object.freeze()方法

自ES5的1.8.5版本起,能够借助Object.freeze()方法来冻结对象,从而防止对象的属性被修改、添加或者删除。示例如下:

1
const DaysEnum = Object.freeze({ "monday": 1, "tuesday": 2, "wednesday": 3 });

或者:

1
2
const DaysEnum = { "monday": 1, "tuesday": 2, "wednesday": 3 };
Object.freeze(DaysEnum);

2. 运用Proxy对象

可以通过Proxy对象模拟传统编程语言中的枚举行为,当尝试访问不存在的枚举项或者添加/更新枚举项时,会抛出错误。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Enum {
constructor(enumObj) {
const handler = {
get(target, name) {
if (typeof target[name] != 'undefined') {
return target[name];
}
throw new Error(`No such enumerator: ${name}`);
},
set() {
throw new Error('Cannot add/update properties on an Enum instance after it is defined');
}
};
return new Proxy(enumObj, handler);
}
}

const roles = new Enum({
ADMIN: 'Admin',
USER: 'User',
});

3. 采用下划线表示法变量

借助下划线表示法变量来定义枚举,能够在代码压缩时减少文件大小,同时提升性能、便于调试和协作。示例如下:

1
2
3
4
5
6
7
8
const ENUM_COLORENUM_RED = 0;
const ENUM_COLORENUM_GREEN = 1;
const ENUM_COLORENUM_BLUE = 2;
const ENUMLEN_COLORENUM = 3;

if (currentColor === ENUM_COLORENUM_RED) {
// do something
}

核心代码

使用Object.freeze()

1
const DaysEnum = Object.freeze({ "monday": 1, "tuesday": 2, "wednesday": 3 });

使用Proxy对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Enum {
constructor(enumObj) {
const handler = {
get(target, name) {
if (typeof target[name] != 'undefined') {
return target[name];
}
throw new Error(`No such enumerator: ${name}`);
},
set() {
throw new Error('Cannot add/update properties on an Enum instance after it is defined');
}
};
return new Proxy(enumObj, handler);
}
}

const httpMethods = new Enum({
DELETE: "DELETE",
GET: "GET",
OPTIONS: "OPTIONS",
PATCH: "PATCH",
POST: "POST",
PUT: "PUT"
});

下划线表示法变量

1
2
3
4
5
6
7
8
const ENUM_COLORENUM_RED = 0;
const ENUM_COLORENUM_GREEN = 1;
const ENUM_COLORENUM_BLUE = 2;
const ENUMLEN_COLORENUM = 3;

if (currentColor === ENUM_COLORENUM_RED) {
// do something
}

最佳实践

  • 使用Object.freeze():适用于简单的枚举定义,能够快速冻结对象,防止属性被修改。
  • 使用Proxy对象:适用于需要严格控制枚举访问和修改的场景,当访问不存在的枚举项或者修改枚举项时,会抛出错误。
  • 下划线表示法变量:适用于大型项目,在代码压缩时能减少文件大小,提升性能,同时便于调试和协作。

常见问题

1. Object.freeze()在旧浏览器中不支持

IE8等旧浏览器不支持Object.freeze()方法。针对这种情况,可以采用字符串常量的方式来定义枚举,示例如下:

1
2
3
4
5
6
var CONST_WILD_TYPES = {
REGULAR: 'REGULAR',
EXPANDING: 'EXPANDING',
STICKY: 'STICKY',
SHIFTING: 'SHIFTING'
};

2. 枚举值被意外修改

即便使用了Object.freeze(),也无法阻止将枚举值赋给变量后,变量被重新赋值。若要实现更强的类型安全,可以使用TypeScript或者Flow等工具。


JavaScript中确保枚举定义不被更改的方法
https://119291.xyz/posts/2025-05-15.methods-to-ensure-enum-definition-unchanged-in-javascript/
作者
ww
发布于
2025年5月15日
许可协议