javascript枚举_JavaScript中的枚举

javascript枚举

A recent post I saw asked how to use Enums in JavaScript, and some of the answers pointed them towards TypeScript. And that’s a good answer … but … it doesn’t solve the problem. How do you use Enums in JavaScript? Let’s explore that.

我最近看到的一则帖子问如何在JavaScript中使用Enums,一些答案将其指向TypeScript。 这是一个很好的答案……但是……并不能解决问题。 您如何在JavaScript中使用枚举? 让我们探索一下。

在您进一步阅读之前: (Before you read further:)

There is no such thing as native Enums in JavaScript. At least, not in the traditional Java/C#/WhatEver Language sense of the word. If you’re looking for a built-in Enum, you’re out of luck. You will need to build your own.

JavaScript中没有原生的Enums。 至少在传统的Java / C#/ WhatEver语言中不是这样。 如果您正在寻找一个内置的枚举,那您就不走运了。 您将需要构建自己的。

Luckily, it’s very easy.

幸运的是,这非常容易。

枚举要求 (The Enum Requirements)

This is what I want to see happen with this class:

这是我想在此类中发生的事情:

let animals = new Enum("Cat", "Dog", "Horse")
console.log(animals.Cat);
console.log(animals.Dog);
console.log(animals.Horse);
animals.Cat = "foobar"; // no change because all are constants
animals.Camel = "foobar" // not added. Only originally declared
// propeties accessible

We are going to start with creating a basic Enum class. Our requirements are:

我们将从创建一个基本的Enum类开始。 我们的要求是:

  1. We declare any number of Enum constants as arguments to the class constructor.

    我们声明任意数量的Enum常量作为类构造函数的参数。
  2. The class will automatically assign a value to those constants.

    该类将自动为这些常量分配一个值。
  3. No constant value can be changed

    不能更改常量值
  4. No items can be added or removed from the class

    不能在课程中添加或删除任何项目

枚举类 (The Enum Class)

Here is the class definition I came up with:

这是我想出的类定义:

class Enum {
constructor(...properties) {
let value = 0;
properties.forEach( function (prop) {
const newValue = value;
Object.defineProperty(this, prop, {
get: function() { return newValue; }
});
value++;
}, this);
Object.freeze(this);
}
}

Let’s take a look as to what’s going on:

让我们看看发生了什么:

First, notice that it has a constructor, but nothing else. This is because there is no need for any other properties. Why? Each property is dynamically created based upon the arguments to the constructor. There is no need to define other properties.

首先,请注意它有一个构造函数,但没有别的。 这是因为不需要任何其他属性。 为什么? 每个属性都是根据构造函数的参数动态创建的。 无需定义其他属性。

Notice also the “rest” syntax as the argument to the constructor. This will take all the arguments we pass to the class and move them into an array. Which means that we can pass a zillion arguments to the constructor and it doesn’t matter to us, as we can access all the arguments as elements of the array. This satisfies Requirement #1 above.

还要注意“ rest”语法作为构造函数的参数。 这将接受我们传递给类的所有参数,并将它们移到数组中。 这意味着我们可以将不计其数的参数传递给构造函数,这对我们来说并不重要,因为我们可以将所有参数作为数组的元素进行访问。 满足上述要求1。

动态创建的属性 (The Dynamically Created Property)

Here’s where the magic occurs. Let’s look at the code:

这就是魔术发生的地方。 让我们看一下代码:

properties.forEach( function (prop) {
const newValue = value;
Object.defineProperty(this, prop, {
get: function() { return newValue; }
});
value++;
}, this);

We loop through the array of all the arguments we pass to the constructor. For each of those properties, we then use “Object.defineProperty” to dynamically add the property to the class. There are a number of things your can do with “Object.defineProperty”, but for us, the important thing is defining “getters” and “setters”. That is, defining a function on how one “gets” the value of the property, and when that property is changed, defining how that value is “set”.

我们遍历传递给构造函数的所有参数的数组。 对于这些属性中的每一个,我们然后使用“ Object.defineProperty”将属性动态添加到类中。 您可以使用“ Object.defineProperty”做很多事情,但是对我们来说,重要的是定义“ getters”和“ setters”。 也就是说,定义一个有关如何“获取”属性值以及何时更改该属性的函数,从而定义如何“设置”该值。

Notice that we’ve only defined “get” and not “set”. This is on purpose. By doing that, any application accessing the property will always get a value, but when they try to set it (change it), nothing will occur. This makes the property “read only”, and satisfies one of our requirements — Requirement #3.

注意,我们仅定义了“ get”而不是“ set”。 这是故意的。 这样,任何访问该属性的应用程序都将始终获得一个值,但是当他们尝试设置(更改)该值时,将不会发生任何事情。 这使该属性为“只读”,并且满足我们的要求之一-要求3。

Finally, the “get” function assigns a number to the property, and increments that number before the next entry in the properties array is called. This effectively assigns an incrementally changing number to each of the properties in order. This satisfies Requirement #2. Why did we reassign “value” to “newValue”? Isn’t that meaningless? Tell you what — pop the code into Node (or a browser) change “newValue” to “value” in the “get” function, and tell me what happens. Extra credit: Tell my why it happens.

最后,“ get”函数为属性分配一个数字,并在调用属性数组中的下一个条目之前递增该数字。 这样可以有效地为每个属性依次分配一个递增更改的数字。 满足要求2。 为什么我们将“价值”重新分配给“新价值”? 那不是没有意义吗? 告诉你什么-将代码弹出到Node(或浏览器)中,在“ get”函数中将“ newValue”更改为“ value”,然后告诉我会发生什么。 额外的信用:告诉我为什么会这样。

冻结对象 (Freezing the Object)

Finally, we have Requirement #4, where nothing can change. This is an easy one-liner:

最后,我们有要求#4,其中什么都不能改变。 这是一个简单的方法:

Object.freeze(this);

Once all the looping is done, we “freeze” the class so that no more changes can be made. This prevents an app from doing something like this:

一旦完成所有循环,我们就“冻结”该类,以便不再进行任何更改。 这样可以防止应用执行以下操作:

let animals = new Enum("Cat", "Dog", "Horse");
animals.Coyote = "my New Animal";

Normally, performing “animals.Coyote” will add the property “Coyote” to the object, and therefor violating Requirement #4. “Freezing” the object prevents this.

通常,执行“ animals.Coyote”会将属性“ Coyote”添加到对象,因此违反了要求4。 “冻结”对象可以防止这种情况。

Just remember that JavaScript will not throw any exception if you try to add a new property to the object.

只要记住,如果您尝试向对象添加新属性,JavaScript将不会引发任何异常。

给枚举赋值 (Assigning Values to Enums)

This is all well and good, but what if you want to assign values to your Enum constants instead of the class doing it for you? Basically eliminating Requirement #2. Some languages let you do this, and you can make a small change in your code to permit that.

这一切都很好,但是,如果您想为Enum常量分配值而不是为您这样做的类怎么办? 基本上消除了要求2。 某些语言允许您执行此操作,并且您可以对代码进行一些小的更改以允许这样做。

Let’s say your assignment now looks like this:

假设您的作业现在看起来像这样:

let animals = new Enum(
{ name: "Cat", value: 2 },
{ name: "Dog", value: 4 },
{ name: "Horse", value: 114 }
);

Instead of just passing the names of the properties, you are passing the names and associated values.

不仅传递属性名称,还传递名称和关联的值。

Your class looks like this:

您的课程如下所示:

class Enum {
constructor(...properties) {
properties.forEach( function (prop) {
const newValue = prop.value;
Object.defineProperty(this, prop.name, {
get: function() { return newValue; }
});
}, this);
Object.freeze(this);
}
}

It’s actually a little smaller than the previous example because it’s not having to increment a counter. The big difference is that the “forEach” loop is now passing an Object to us with two properties, “name” and “value”. The only thing that changed was the assignment of the “newValue” variable from “value” to “prop.value” and the second argument to the “Object.defineProperty” method, which changed from “prop” to “prop.name”.

实际上,它比前面的示例要小一些,因为它不必增加计数器。 最大的区别在于,“ forEach”循环现在通过一个具有“ name”和“ value”两个属性的Object传递给我们。 唯一更改的是将“ newValue”变量从“值”分配给“ prop.value”,并将第二个参数分配给“ Object.defineProperty”方法,该方法从“ prop”更改为“ prop.name”。

This new definition will now let you not only create your enums, but also assign values to them.

现在,此新定义将使您不仅可以创建枚举,还可以为它们分配值。

摘要 (Summary)

If you miss your Enum classes and data constructs in other languages once you went to JavaScript, the above should get you started in recreating Enums and making your life happy again.

如果您在使用JavaScript时错过了其他语言的Enum类和数据构造,那么上面的内容应该可以帮助您重新创建Enums并重新过上幸福的生活。

See you later!

回头见!

P.S.

聚苯乙烯

Extra Credit: Do this:

额外信用:执行以下操作:

let animals = new Enum("Cat", "Dog", "Horse");
console.log(animals);
// displays the following:
// Enum {}

You’ll see nothing listed. It’s all because of the arguments passed to “Object.defineProperty”. Look it up and figure out what you need to do to get the following listing:

您将看不到任何内容。 这是因为传递给“ Object.defineProperty”的参数。 查找它,弄清楚需要做什么才能获得以下清单:

let animals = new Enum("Cat", "Dog", "Horse");
console.log(animals);
// displays the following:
// Enum { Cat: [Getter], Dog: [Getter], Horse: [Getter] }

翻译自: https://medium.com/@thevirtuoid/enums-in-javascript-e3f1be4a3cb5

javascript枚举

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值