ES6 সহ জাভাস্ক্রিপ্টে এনামগুলি


136

আমি জাভাস্ক্রিপ্টে একটি পুরানো জাভা প্রকল্পটি পুনর্নির্মাণ করছি এবং বুঝলাম যে জেএসে এনামগুলি করার ভাল কোনও উপায় নেই।

আমি যে সেরাটি নিয়ে আসতে পারি তা হ'ল:

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

constরাখে Colorsপুনরায় নির্ধারণ হওয়া থেকে, এবং জমাকৃত এটা কী ও মান mutating বাধা দেয়। আমি সিম্বলসটি ব্যবহার করছি যাতে এটির Colors.REDসমান নয় 0বা নিজে ছাড়া অন্য কিছু।

এই সূত্রটি নিয়ে কোনও সমস্যা আছে? একটি ভাল উপায় আছে কি?


(আমি জানি এই প্রশ্নটি কিছুটা পুনরাবৃত্তি, তবে পূর্ববর্তী সমস্ত প্রশ্ন / হিসাবে বেশ পুরানো, এবং ES6 আমাদের কিছু নতুন ক্ষমতা দেয়))


সম্পাদনা করুন:

সিরিয়ালাইজেশন সমস্যার সাথে মোকাবিলা করা অন্য একটি সমাধান, তবে আমি বিশ্বাস করি যে এখনও রাজ্যের সমস্যা রয়েছে:

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

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

মান হিসাবে বস্তু রেফারেন্স ব্যবহার করে, আপনি প্রতীক হিসাবে একই সংঘর্ষ-এড়ানো।


2
এটি এস in এ একটি নিখুঁত পদ্ধতির হবে। আপনার এটি
হিম

2
@ নীরাস আপনি করেন, আপনি যদি এটি পরিবর্তন না চান।
zerkms

2
আপনি কি এই উত্তর লক্ষ্য করেছেন ?
বার্গি

3
আমি ভাবতে পারি এমন একটি সমস্যা: এই এনামটি ব্যবহার করতে পারি না JSON.stringify()। সিরিয়ালাইজ / ডিসরিয়ালাইজ করা যায় না Symbol
le_m

1
@ ইরেকে রেড আমি কয়েক বছর ধরে স্ট্রিং এনামের ধ্রুবক মানগুলি কোনও ঝামেলা ছাড়াই ব্যবহার করে চলেছি কারণ ফ্লো (বা টাইপসক্রিপ্ট) ব্যবহারের ফলে সংঘর্ষ এড়ানোর বিষয়ে ঝাঁকুনির চেয়ে আরও বেশি ধরণের সুরক্ষার নিশ্চয়তা পাওয়া যায়
অ্যান্ডি

উত্তর:


131

এই সূত্রটি নিয়ে কোনও সমস্যা আছে?

আমি কিছুই দেখতে পাচ্ছি না।

একটি ভাল উপায় আছে কি?

আমি দুটি বিবৃতি একটিতে ভেঙে দেব:

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

আপনি যদি বয়লারপ্লেট পছন্দ না করেন তবে বারবার পছন্দ করুন Symbol কলগুলির অবশ্যই একটি সহায়ক ফাংশন লিখতে পারেন makeEnumযা নামের তালিকা থেকে একই জিনিসটি তৈরি করে।


3
এখানে কি রাজ্যের সমস্যা নেই?

2
@ টোরাজাবুরো আপনার অর্থ, কোডটি দু'বার লোড করা হলে এটি বিভিন্ন চিহ্ন তৈরি করবে, যা স্ট্রিংগুলির সাথে কোনও সমস্যা হবে না? হ্যাঁ, ভাল কথা, একটি উত্তর দিন :-)
বার্গি

2
@ErictheRed না, Symbol.forনেই না ক্রস রাজত্ব বিষয় আছে, তবে এটি একটি সঙ্গে স্বাভাবিক সংঘর্ষের সমস্যা আছে সত্যিকারের আন্তর্জাতিক নামস্থান
বার্গি

1
@ ইরিকের রেড এটি কখন এবং কোথায় (যা থেকে রাজ্য / ফ্রেম / ট্যাব / প্রক্রিয়া বলা হয়) নির্বিশেষে সঠিক একই প্রতীক তৈরির নিশ্চয়তা দেয়
বার্গি

1
@ জামেসিমনন আপনি চাইলে বর্ণনাটি পেতে পারেন তবে আমি এটি প্রাথমিকভাবে কেবল ডিবাগিংয়ের জন্যই ব্যবহার করব। বরং যথারীতি একটি কাস্টম এনাম-টু-স্ট্রিং রূপান্তর ফাংশন রাখুন (লাইনগুলির সাথে কিছু enum => ({[Colors.RED]: "bright red", [Colors.BLUE]: "deep blue", [Colors.GREEN]: "grass green"}[enum]))।
বার্গি

18

ব্যবহার যতক্ষণ Symbolযেমন enum মান সহজ ব্যবহারের ক্ষেত্রে জন্য কাজ করে জরিমানা, এটা enums করার বৈশিষ্ট্য দিতে কুশলী হতে পারে। এটি Objectবৈশিষ্ট্যযুক্ত এনাম মান হিসাবে ব্যবহার করে করা যেতে পারে ।

উদাহরণস্বরূপ আমরা প্রতিটি Colorsনাম এবং হেক্স মান দিতে পারি:

/**
 * 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" }
});

এনামের বৈশিষ্ট্যগুলি অন্তর্ভুক্ত করে switchবিবৃতি লিখতে হবে (এবং সম্ভবত এনুম বাড়ানো হলে স্যুইচ স্টেটমেন্টগুলিতে নতুন কেসগুলি ভুলে যাওয়া)। উদাহরণটি এনএস বৈশিষ্ট্য এবং জেএসডোক এনাম টীকা সহ নথিভুক্ত প্রকারগুলিও দেখায় ।

সমতাটি Colors.RED === Colors.REDসত্তা trueColors.RED === Colors.BLUEসত্তার সাথে প্রত্যাশা অনুযায়ী কাজ করে false


9

উপরে উল্লিখিত হিসাবে, আপনি একটি 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");
}

2
ওয়ান-লাইনার হিসাবে: const makeEnum = (...lst) => Object.freeze(Object.assign({}, ...lst.map(k => ({[k]: Symbol(k)})))); তারপরে এটি ব্যবহার করুন const colors = makeEnum("Red", "Green", "Blue")
ম্যানুয়েল এবার্ট

9

এটি আমার ব্যক্তিগত পদ্ধতি।

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);

আমি এটি ব্যবহার করার পরামর্শ দেব না কারণ এটি সমস্ত সম্ভাব্য মানগুলির সাথে পুনরাবৃত্তি করার কোনও উপায় সরবরাহ করে না এবং প্রতিটিটির জন্য নিজে নিজে পরীক্ষা না করে কোনও মান একটি কালার টাইপ কিনা তা পরীক্ষা করার কোনও উপায় নেই।
ডোমিনো

7

চেক কীভাবে এটি টাইপস্ক্রিপ্ট করে তা করে দেখুন । মূলত তারা নিম্নলিখিতটি করে:

const MAP = {};

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

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

আপনি যা চান প্রতীক, নিথর বস্তু ব্যবহার করুন।


আমি এটি অনুসরণ করছি না কেন এটি MAP[MAP[1] = 'A'] = 1;পরিবর্তে ব্যবহার করে MAP[1] = 'A'; MAP['A'] = 1;। আমি সবসময় শুনেছি যে কোনও অ্যাসাইনমেন্টকে এক্সপ্রেশন হিসাবে ব্যবহার করা খারাপ স্টাইল। এছাড়াও, মিররযুক্ত অ্যাসাইনমেন্টগুলি থেকে আপনি কী সুবিধা পাবেন?
এরিক দি রেড

1
এখানে এনাম ম্যাপিং কীভাবে তাদের ডক্সে এস 5 তে সংকলিত হয় তার একটি লিঙ্ক এখানে দেওয়া হয়েছে। টাইপসক্রিপ্টআরএল.এগ. / ডকস / হ্যান্ডবুক / এনমস এইচটিএমএল# রিভার্স- ম্যাপিংস আমি চিত্রটি তুলতে পারি যে এটি একক লাইনে সংকলন করা সহজ এবং আরও সংক্ষিপ্ত হবে MAP[MAP[1] = 'A'] = 1;
গিহাগ

হাহ। সুতরাং দেখে মনে হচ্ছে মিররিংটি প্রতিটি মানের স্ট্রিং এবং সংখ্যা / প্রতীক উপস্থাপনার মধ্যে স্যুইচ করা সহজ করে দেয় এবং পরীক্ষা করে দেখুন যে কিছু স্ট্রিং বা সংখ্যা / চিহ্ন xএকটি বৈধ এনুম মান হয় Enum[Enum[x]] === x। এটি আমার মূল সমস্যাগুলির কোনও সমাধান করে না, তবে এটি কার্যকর হতে পারে এবং কোনও কিছুতেই ভাঙবে না।
এরিক দ্য রেড

1
মনে রাখবেন যে টাইপস্ক্রিপ্ট দৃ rob়তার একটি স্তর যুক্ত করে যা টিএস কোড সংকলনের পরে হারিয়ে যায়। যদি আপনার পুরো অ্যাপটি টিএস-তে লেখা থাকে তবে এটি দুর্দান্ত, তবে আপনি যদি জেএস কোডটি শক্তিশালী হতে চান তবে প্রতীকগুলির হিমায়িত মানচিত্রটি একটি নিরাপদ নিদর্শন বলে মনে হচ্ছে।
ডোমিনো



1

এই সমাধান হতে পারে? :)

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

উদাহরণ:

createEnum(['red', 'green', 'blue']);

> {RED: Symbol(red), GREEN: Symbol(green), BLUE: Symbol(blue)}

ব্যবহারের উদাহরণটি সত্যই প্রশংসা করা হবে :-)
আবদাররহমানে তাহরি জৌটি

0

আমি ES6 / নোড.জেএস বাস্তুতন্ত্রের অন্তর্নিহিতগুলি আরও ভালভাবে বোঝার সুবিধার জন্য কিছুটা বর্ধন এবং খনন সহ @ টোনেথারের পদ্ধতিকে পছন্দ করি। বেড়ার সার্ভার সাইডের একটি পটভূমি সহ, আমি প্ল্যাটফর্মের আদিমদের চারপাশে কার্যকরী শৈলীর পদ্ধতির পছন্দকে প্রাধান্য দিয়েছি, এটি কোড ব্লাটকে কমিয়ে দেয়, নতুন প্রকারের প্রবর্তনের কারণে মৃত্যুর ছায়ার রাজ্যের পরিচালনা উপত্যকায় পিচ্ছিল slাল। পাঠযোগ্যতা - সমাধানের উদ্দেশ্য এবং অ্যালগরিদমকে আরও পরিষ্কার করে তোলে।

সঙ্গে সমাধান TDD- এ , ES6 , Node.js , Lodash , ঠাট্টা , হট্টগোল , ESLint

// ./utils.js
import _ from 'lodash';

const enumOf = (...args) =>
  Object.freeze( Array.from( Object.assign(args) )
    .filter( (item) => _.isString(item))
    .map((item) => Object.freeze(Symbol.for(item))));

const sum = (a, b) => a + b;

export {enumOf, sum};
// ./utils.js

// ./kittens.js
import {enumOf} from "./utils";

const kittens = (()=> {
  const Kittens = enumOf(null, undefined, 'max', 'joe', 13, -13, 'tabby', new 
    Date(), 'tom');
  return () => Kittens;
})();

export default kittens();
// ./kittens.js 

// ./utils.test.js
import _ from 'lodash';
import kittens from './kittens';

test('enum works as expected', () => {
  kittens.forEach((kitten) => {
    // in a typed world, do your type checks...
    expect(_.isSymbol(kitten));

    // no extraction of the wrapped string here ...
    // toString is bound to the receiver's type
    expect(kitten.toString().startsWith('Symbol(')).not.toBe(false);
    expect(String(kitten).startsWith('Symbol(')).not.toBe(false);
    expect(_.isFunction(Object.valueOf(kitten))).not.toBe(false);

    const petGift = 0 === Math.random() % 2 ? kitten.description : 
      Symbol.keyFor(kitten);
    expect(petGift.startsWith('Symbol(')).not.toBe(true);
    console.log(`Unwrapped Christmas kitten pet gift '${petGift}', yeee :) 
    !!!`);
    expect(()=> {kitten.description = 'fff';}).toThrow();
  });
});
// ./utils.test.js

Array.from(Object.assign(args))একেবারে কিছুই করে না আপনি কেবল ...argsসরাসরি ব্যবহার করতে পারেন ।
ডোমিনো

0

এখানে কিছু সহায়তাকারী পদ্ধতি সহ আমার পন্থা

export default class Enum {

    constructor(name){
        this.name = name;
    }

    static get values(){
        return Object.values(this);
    }

    static forName(name){
        for(var enumValue of this.values){
            if(enumValue.name === name){
                return enumValue;
            }
        }
        throw new Error('Unknown value "' + name + '"');
    }

    toString(){
        return this.name;
    }
}

-

import Enum from './enum.js';

export default class ColumnType extends Enum {  

    constructor(name, clazz){
        super(name);        
        this.associatedClass = clazz;
    }
}

ColumnType.Integer = new ColumnType('Integer', Number);
ColumnType.Double = new ColumnType('Double', Number);
ColumnType.String = new ColumnType('String', String);

0

আপনি es6-enum প্যাকেজও ব্যবহার করতে পারেন ( https://www.npmjs.com/package/es6-enum )। এটি ব্যবহার করা খুব সহজ। নীচের উদাহরণটি দেখুন:

import Enum from "es6-enum";
const Colors = Enum("red", "blue", "green");
Colors.red; // Symbol(red)

10
নীচে কোন উদাহরণ?
আলেকজান্ডার

আপনি যদি উদাহরণ তৈরি করেন, লোকেরা আপনার উত্তরের পক্ষে ভোট দেবে।
আর্টেম ফেদোটভ

0

এখানে আমার জাভাস্ক্রিপ্টে একটি জাভা গণনার বাস্তবায়ন।

আমি ইউনিট পরীক্ষা অন্তর্ভুক্ত।

const main = () => {
  mocha.setup('bdd')
  chai.should()

  describe('Test Color [From Array]', function() {
    let Color = new Enum('RED', 'BLUE', 'GREEN')
    
    it('Test: Color.values()', () => {
      Color.values().length.should.equal(3)
    })

    it('Test: Color.RED', () => {
      chai.assert.isNotNull(Color.RED)
    })

    it('Test: Color.BLUE', () => {
      chai.assert.isNotNull(Color.BLUE)
    })

    it('Test: Color.GREEN', () => {
      chai.assert.isNotNull(Color.GREEN)
    })

    it('Test: Color.YELLOW', () => {
      chai.assert.isUndefined(Color.YELLOW)
    })
  })

  describe('Test Color [From Object]', function() {
    let Color = new Enum({
      RED   : { hex: '#F00' },
      BLUE  : { hex: '#0F0' },
      GREEN : { hex: '#00F' }
    })

    it('Test: Color.values()', () => {
      Color.values().length.should.equal(3)
    })

    it('Test: Color.RED', () => {
      let red = Color.RED
      chai.assert.isNotNull(red)
      red.getHex().should.equal('#F00')
    })

    it('Test: Color.BLUE', () => {
      let blue = Color.BLUE
      chai.assert.isNotNull(blue)
      blue.getHex().should.equal('#0F0')
    })

    it('Test: Color.GREEN', () => {
      let green = Color.GREEN
      chai.assert.isNotNull(green)
      green.getHex().should.equal('#00F')
    })

    it('Test: Color.YELLOW', () => {
      let yellow = Color.YELLOW
      chai.assert.isUndefined(yellow)
    })
  })

  mocha.run()
}

class Enum {
  constructor(values) {
    this.__values = []
    let isObject = arguments.length === 1
    let args = isObject ? Object.keys(values) : [...arguments]
    args.forEach((name, index) => {
      this.__createValue(name, isObject ? values[name] : null, index)
    })
    Object.freeze(this)
  }

  values() {
    return this.__values
  }

  /* @private */
  __createValue(name, props, index) {
    let value = new Object()
    value.__defineGetter__('name', function() {
      return Symbol(name)
    })
    value.__defineGetter__('ordinal', function() {
      return index
    })
    if (props) {
      Object.keys(props).forEach(prop => {
        value.__defineGetter__(prop, function() {
          return props[prop]
        })
        value.__proto__['get' + this.__capitalize(prop)] = function() {
          return this[prop]
        }
      })
    }
    Object.defineProperty(this, name, {
      value: Object.freeze(value),
      writable: false
    })
    this.__values.push(this[name])
  }

  /* @private */
  __capitalize(str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
  }
}

main()
.as-console-wrapper {
  top: 0;
  max-height: 100% !important;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.2.5/mocha.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.2.5/mocha.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.2.0/chai.js"></script>
<!--

public enum Color {
  RED("#F00"),
  BLUE("#0F0"),
  GREEN("#00F");
  
  private String hex;
  public String getHex()  { return this.hex;  }
  
  private Color(String hex) {
    this.hex = hex;
  }
}

-->
<div id="mocha"></div>


-3

আপনি ES6 মানচিত্র ব্যবহার করতে পারে

const colors = new Map([
  ['RED', 'red'],
  ['BLUE', 'blue'],
  ['GREEN', 'green']
]);

console.log(colors.get('RED'));

আইএমএইচও এটির একটি জটিল সমাধান কারণ এটি প্রতিটি জটিলতার জন্য (প্রতিটি বার অ্যাকসেসর পদ্ধতিটি কল করা উচিত) এবং এনাম প্রকৃতির radপন্যাস (মিউটর পদ্ধতিটি কল করতে পারে এবং কোনও কীটির একটি মান পরিবর্তন করতে পারে) ... সুতরাং const x = Object.freeze({key: 'value'})পরিবর্তে কিছু দেখতে পাওয়া যায় যা দেখতে পাওয়া যায় এবং ES6 এ
এনামের

কালার্স.জেট ('রেড') এর মতো করে মানটি পেতে আপনাকে অবশ্যই একটি স্ট্রিং পাস করতে হবে। যা ত্রুটি প্রবণ।
অ্যাড্রিয়ান oviedo
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.