web-dev-qa-db-ja.com

ES6によるJavascriptの列挙型

私はJavascriptで古いJavaプロジェクトを再構築していますが、JSで列挙型を作成するには良い方法がないことに気付きました。

私が思い付くことができる最高のものは:

const Colors = {
    RED: Symbol("red"),
    BLUE: Symbol("blue"),
    GREEN: Symbol("green")
};
Object.freeze(Colors);

constColorsが再割り当てされるのを防ぎ、凍結することでキーと値の変更を防ぎます。 Colors.RED0、またはそれ以外の何かに等しくないように、私はSymbolsを使っています。

この定式化に問題はありますか?もっと良い方法はありますか?


(この質問はちょっとした繰り返しであることを私は知っていますが、以前の 以前のQ/As は非常に古く、ES6によればいくつかの新しい機能。)


編集:

シリアライゼーションの問題に対処するもう1つの解決策。ただし、まだレルムの問題があると思います。

const enumValue = (name) => Object.freeze({toString: () => name});

const Colors = Object.freeze({
    RED: enumValue("Colors.RED"),
    BLUE: enumValue("Colors.BLUE"),
    GREEN: enumValue("Colors.GREEN")
});

値としてオブジェクト参照を使用することで、Symbolsと同じ衝突回避が得られます。

90
Eric the Red

この定式化に問題はありますか?

見えません。

もっと良い方法はありますか?

2つのステートメントを1つにまとめます。

const Colors = Object.freeze({
    RED:   Symbol("red"),
    BLUE:  Symbol("blue"),
    GREEN: Symbol("green")
});

Symbolの繰り返し呼び出しのように定型句が気に入らない場合は、もちろん、名前のリストから同じものを作成するヘルパー関数makeEnumを書くこともできます。

92
Bergi

TypeScriptがどのように動作するか を確認してください 。基本的に彼らは以下のことを行います。

const MAP = {};

MAP[MAP[1] = 'A'] = 1;
MAP[MAP[2] = 'B'] = 2;

MAP['A'] // 1
MAP[1] // A

あなたが望むものは何でも、シンボルを使用して、オブジェクトを凍結してください。

5
givehug

Enum値としてSymbolを使用することは単純なユースケースのためにうまく働きますが、enumにプロパティを与えることは便利かもしれません。これは、プロパティを含む列挙値としてObjectを使用することによって実行できます。

たとえば、それぞれのColorsに名前と16進値を付けることができます。

/**
 * Enum for common colors.
 * @readonly
 * @enum {{name: string, hex: string}}
 */
const Colors = Object.freeze({
  RED:   { name: "red", hex: "#f00" },
  BLUE:  { name: "blue", hex: "#00f" },
  GREEN: { name: "green", hex: "#0f0" }
});

Enumにプロパティを含めることで、switchステートメントを書く必要がなくなります(そしてenumが拡張されたときにswitchステートメントの新しいケースを忘れることもあります)。この例では、 JSDoc enumアノテーション で文書化されたenumプロパティと型も示しています。

Colors.RED === Colors.REDtrueで、Colors.RED === Colors.BLUEfalseであれば、平等は期待通りに働きます。

5
Justin Emery

ES6列挙型の非常に優れた機能を備えたライブラリである Enumify を確認できます。

4
Emmanuel.B

上記のように、makeEnum()ヘルパー関数を書くこともできます。

function makeEnum(arr){
    let obj = {};
    for (let val of arr){
        obj[val] = Symbol(val);
    }
    return Object.freeze(obj);
}

このように使用してください。

const Colors = makeEnum(["red","green","blue"]);
let startColor = Colors.red; 
console.log(startColor); // Symbol(red)

if(startColor == Colors.red){
    console.log("Do red things");
}else{
    console.log("Do non-red things");
}
4
tonethar

あなたが純粋なES6を必要とせず、TypeScriptを使うことができるなら、それはNice enumを持っています:

https://www.typescriptlang.org/docs/handbook/enums.html

2
Chris Halcrow

これが私の個人的なやり方です。

class ColorType {
    static get RED () {
        return "red";
    }

    static get GREEN () {
        return "green";
    }

    static get BLUE () {
        return "blue";
    }
}

// Use case.
const color = Color.create(ColorType.RED);

たぶんこの解決策? :)

function createEnum (array) {
  return Object.freeze(array
    .reduce((obj, item) => {
      if (typeof item === 'string') {
        obj[item] = Symbol(item)
      }
      return obj
    }, {}))
}
1