Какой синтаксис является предпочтительным для определения перечислений в JavaScript? [закрыто]

Нравится это:

from c in db.Company
group c by c.Name into grp
where grp.Count() > 1
select grp.Key

Или, используя синтаксис метода:

Company
    .GroupBy(c => c.Name)
    .Where(grp => grp.Count() > 1)
    .Select(grp => grp.Key);
1918
задан DAIRAV 26 December 2018 в 06:38
поделиться

44 ответа

Простейшее решение:

Создать

var Status = Object.freeze({
    "Connecting":0,
    "Ready":1,
    "Loading":2,
    "Processing": 3
});

Получить значение

console.log(Status.Ready) // 1

Получить ключ

console.log(Object.keys(Status)[Status.Ready]) // Ready
3
ответ дан Ilya Gazman 26 December 2018 в 06:38
поделиться

Давайте обратимся прямо к проблеме: размер файла. Любой другой ответ, перечисленный здесь, увеличивает ваш код до крайности. Я представляю вам, что для наилучшей производительности, читабельности кода, управления крупномасштабными проектами, подсказок синтаксиса во многих редакторах кода и уменьшения размера кода путем минимизации, это правильный способ сделать перечисления: переменные с подчеркиванием-нотацией.


<час>

Underscore-Notation Variables

const ENUM_COLORENUM_RED   = 0,
      ENUM_COLORENUM_GREEN = 1,
      ENUM_COLORENUM_BLUE  = 2,
      ENUMLEN_COLORENUM    = 3;

// later on

if(currentColor === ENUM_COLORENUM_RED) {
   // whatever
}


[1118]

<час >

22
ответ дан Jack Giffin 26 December 2018 в 06:38
поделиться

Я сделал это некоторое время назад, используя смесь __defineGetter__ и __defineSetter__ или defineProperty в зависимости от версии JS.

Вот функция генерации перечисления, которую я сделал: https://gist.github.com/gfarrell/6716853

Вы бы использовали это так:

var Colours = Enum('RED', 'GREEN', 'BLUE');

И это создаст неизменную строку: словарь int (перечисление).

2
ответ дан GTF 26 December 2018 в 06:38
поделиться

Используйте Javascript Прокси

TLDR: Добавьте этот класс к своим служебным методам и используйте его во всем коде, он имитирует поведение Enum из традиционных языков программирования и фактически выдает ошибки, когда вы пытаетесь получить доступ к не существующему перечислителю или добавить / обновить перечислитель. Не нужно полагаться на Object.freeze().

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',
});

Полное объяснение:

Одна очень полезная особенность Enums, которую вы получаете по сравнению с традиционными языками они взрываются (выдают ошибку во время компиляции), если вы пытаетесь получить доступ к перечислителю, который не существует.

Помимо замораживания поддельной структуры enum для предотвращения случайного / злонамеренного добавления дополнительных значений, ни один из других ответов не затрагивает эту внутреннюю особенность Enums.

Как вы, вероятно, знаете, доступ к несуществующим элементам в JavaScript просто возвращает undefined и не взрывает ваш код. Поскольку перечислители являются предопределенными константами (т.е. днями недели), никогда не должно быть случая, когда перечислитель должен быть неопределенным.

Не поймите меня неправильно, поведение JavaScript, возвращающее undefined при доступе к неопределенным свойствам, на самом деле является очень мощной функцией языка, но это не та функция, которая вам нужна, когда вы пытаетесь смоделировать традиционные структуры Enum.

Здесь прокси объекты сияют. Прокси были стандартизированы в языке с введением ES6 (ES2015). Вот описание из MDN:

Объект Proxy используется для определения пользовательского поведения для основных операций (например, поиск свойств, присваивание, перечисление, вызов функции и т. Д.).

Подобно прокси-серверу веб-сервера, прокси-серверы JavaScript способны перехватывать операции над объектами (с использованием «ловушек», вызывать их, если хотите), и позволяют выполнять различные проверки, действия и / или манипуляции до того, как они завершатся (или в некоторых случаях вообще останавливают операции, что мы и хотим делать, если и когда мы пытаемся ссылаться на перечислитель, который не существует).

Вот надуманный пример, который использует объект Proxy для имитации Enums. В этом примере перечислители являются стандартными методами HTTP (т. Е. "GET", "POST" и т. Д.):

// Class for creating enums (13 lines)
// Feel free to add this to your utility library in 
// your codebase and profit! Note: As Proxies are an ES6 
// feature, some browsers/clients may not support it and 
// you may need to transpile using a service like babel

class Enum {
  // The Enum class instantiates a JavaScript Proxy object.
  // Instantiating a `Proxy` object requires two parameters, 
  // a `target` object and a `handler`. We first define the handler,
  // then use the handler to instantiate a Proxy.

  // A proxy handler is simply an object whose properties
  // are functions which define the behavior of the proxy 
  // when an operation is performed on it. 
  
  // For enums, we need to define behavior that lets us check what enumerator
  // is being accessed and what enumerator is being set. This can be done by 
  // defining "get" and "set" traps.
  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')
      }
    }


    // Freeze the target object to prevent modifications
    return new Proxy(enumObj, handler)
  }
}


// Now that we have a generic way of creating Enums, lets create our first Enum!
const httpMethods = new Enum({
  DELETE: "DELETE",
  GET: "GET",
  OPTIONS: "OPTIONS",
  PATCH: "PATCH",
  POST: "POST",
  PUT: "PUT"
})

// Sanity checks
console.log(httpMethods.DELETE)
// logs "DELETE"

try {
  httpMethods.delete = "delete"
} catch (e) {
console.log("Error: ", e.message)
}
// throws "Cannot add/update properties on an Enum instance after it is defined"

try {
  console.log(httpMethods.delete)
} catch (e) {
  console.log("Error: ", e.message)
}
// throws "No such enumerator: delete"

ВНЕ: Какого черта это прокси?

Я помню, когда я впервые увидел слово прокси везде, это определенно не имело смысла для меня долгое время. Если это вы сейчас, я думаю, что простой способ обобщить прокси - это думать о них как о программном обеспечении, учреждениях или даже людях, которые выступают в качестве посредников или посредников между двумя серверами, компаниями или людьми.

17
ответ дан j2k 26 December 2018 в 06:38
поделиться

Вот как Typescript переводит его enum в Javascript:

var makeEnum = function(obj) {
    obj[ obj['Active'] = 1 ] = 'Active';
    obj[ obj['Closed'] = 2 ] = 'Closed';
    obj[ obj['Deleted'] = 3 ] = 'Deleted';
}

Теперь:

makeEnum( NewObj = {} )
// => {1: "Active", 2: "Closed", 3: "Deleted", Active: 1, Closed: 2, Deleted: 3}

Сначала я был озадачен, почему obj[1] возвращает 'Active', но затем понял, что его просто - оператор присваивания присваивает значение, а затем возвращает его:

obj['foo'] = 1
// => 1
4
ответ дан Julius Dzidzevičius 26 December 2018 в 06:38
поделиться

IE8 не поддерживает метод freeze ().
Источник: http://kangax.github.io/compat-table/es5/ , нажмите "Показать устаревшие браузеры?" сверху и проверьте IE8 & amp; пересечение строк замораживания строк.

В моем текущем игровом проекте я использовал ниже, так как мало клиентов все еще используют IE8:

var CONST_WILD_TYPES = {
    REGULAR: 'REGULAR',
    EXPANDING: 'EXPANDING',
    STICKY: 'STICKY',
    SHIFTING: 'SHIFTING'
};

Мы могли бы также сделать:

var CONST_WILD_TYPES = {
    REGULAR: 'RE',
    EXPANDING: 'EX',
    STICKY: 'ST',
    SHIFTING: 'SH'
};

или даже это:

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

Последнее, кажется, наиболее эффективно для строки, оно уменьшает вашу общую пропускную способность, если у вас есть сервер & amp; клиент обменивается этими данными.
Конечно, теперь вы обязаны убедиться, что в данных нет конфликтов (RE, EX и т. Д. Должны быть уникальными, а также 1, 2 и т. Д. Должны быть уникальными). Обратите внимание, что вы должны поддерживать их всегда для обратной совместимости.

Назначение:

var wildType = CONST_WILD_TYPES.REGULAR;

Сравнение:

if (wildType === CONST_WILD_TYPES.REGULAR) {
    // do something here
}
6
ответ дан Manohar Reddy Poreddy 26 December 2018 в 06:38
поделиться
var ColorEnum = {
    red: {},
    green: {},
    blue: {}
}

Вам не нужно следить за тем, чтобы таким образом не назначать повторяющиеся числа различным значениям перечисления. Новый объект создается и присваивается всем значениям перечисления.

4
ответ дан Shivanshu Goyal 26 December 2018 в 06:38
поделиться

На момент написания статьи октябрь 2014 г. - так вот современное решение. Пишу решение в виде Node Module и включаю тест с использованием Mocha и Chai, а также underscoreJS. Вы можете легко их игнорировать и просто взять код Enum, если хотите.

Видел много постов с чрезмерно запутанными библиотеками и т. Д. Решение получить поддержку enum в Javascript настолько простое, что действительно не нужно. Вот код:

Файл: enums.js

_ = require('underscore');

var _Enum = function () {

   var keys = _.map(arguments, function (value) {
      return value;
   });
   var self = {
      keys: keys
   };
   for (var i = 0; i < arguments.length; i++) {
      self[keys[i]] = i;
   }
   return self;
};

var fileFormatEnum = Object.freeze(_Enum('CSV', 'TSV'));
var encodingEnum = Object.freeze(_Enum('UTF8', 'SHIFT_JIS'));

exports.fileFormatEnum = fileFormatEnum;
exports.encodingEnum = encodingEnum;

И тест для иллюстрации того, что он вам дает:

file: enumsSpec.js

var chai = require("chai"),
    assert = chai.assert,
    expect = chai.expect,
    should = chai.should(),
    enums = require('./enums'),
    _ = require('underscore');


describe('enums', function () {

    describe('fileFormatEnum', function () {
        it('should return expected fileFormat enum declarations', function () {
            var fileFormatEnum = enums.fileFormatEnum;
            should.exist(fileFormatEnum);
            assert('{"keys":["CSV","TSV"],"CSV":0,"TSV":1}' === JSON.stringify(fileFormatEnum), 'Unexpected format');
            assert('["CSV","TSV"]' === JSON.stringify(fileFormatEnum.keys), 'Unexpected keys format');
        });
    });

    describe('encodingEnum', function () {
        it('should return expected encoding enum declarations', function () {
            var encodingEnum = enums.encodingEnum;
            should.exist(encodingEnum);
            assert('{"keys":["UTF8","SHIFT_JIS"],"UTF8":0,"SHIFT_JIS":1}' === JSON.stringify(encodingEnum), 'Unexpected format');
            assert('["UTF8","SHIFT_JIS"]' === JSON.stringify(encodingEnum.keys), 'Unexpected keys format');
        });
    });

});

Как видите, вы получаете фабрику Enum, вы можете получить все ключи, просто вызвав enum.keys, и вы можете сопоставить сами ключи с целочисленными константами. И вы можете повторно использовать фабрику с другими значениями и экспортировать сгенерированные Enums, используя модульный подход Node.

Еще раз, если вы обычный пользователь или в браузере и т. Д., Просто возьмите заводскую часть кода, потенциально удалив также библиотеку подчеркивания, если вы не хотите использовать ее в своем коде.

3
ответ дан arcseldon 26 December 2018 в 06:38
поделиться

Вы можете использовать простую функцию для инвертирования ключей и значений, она будет работать и с массивами, поскольку она преобразует числовые целочисленные строки в числа. Код небольшой, простой и многократно используемый для этого и других случаев использования.

var objInvert = function (obj) {
    var invert = {}
    for (var i in obj) {
      if (i.match(/^\d+$/)) i = parseInt(i,10)
      invert[obj[i]] = i
    }
    return invert
}
 
var musicStyles = Object.freeze(objInvert(['ROCK', 'SURF', 'METAL',
'BOSSA-NOVA','POP','INDIE']))

console.log(musicStyles)
0
ответ дан David Lemon 26 December 2018 в 06:38
поделиться

Что такое перечисление в моем мнении : это неизменный объект, который всегда доступен, и вы можете сравнивать элементы друг с другом, но элементы имеют общие свойства / методы, но сами объекты или значения не могут быть изменены, и они создаются только один раз.

Перечисления imho используются для сравнения типов данных, настроек, действий для принятия / ответа на подобные вещи.

Итак, для этого вам нужны объекты с одинаковым экземпляром, чтобы вы могли проверить, является ли это типом enum. if(something instanceof enum) Также, если вы получаете объект enum, вы хотите иметь возможность что-то с ним делать, независимо от того, Тип enum, он всегда должен отвечать одинаково.

В моем случае сравниваются значения типов данных, но это может быть что угодно: от изменения блоков в направлении движения в трехмерной игре до передачи значений в реестр конкретных типов объектов.

Имея в виду, что это javascript и он не предоставляет фиксированный тип enum, вы в конечном итоге всегда делаете свою собственную реализацию, и, как показывает этот поток, существуют легионы реализаций, хотя одна из них не является абсолютной верностью.


Это то, что я использую для Enums. Поскольку перечисления неизменяемы (или должны быть хотя бы хе), я замораживаю объекты, чтобы ими нельзя было легко манипулировать.

EnumField.STRING может использовать перечисления, и они имеют свои собственные методы, которые будут работать с их типами. Чтобы проверить, передано ли что-либо объекту, вы можете использовать if(somevar instanceof EnumFieldSegment)

Возможно, это не самое элегантное решение, и я открыт для улучшений, но этот тип неизменяемого перечисления (если вы не разморозили его) точно нужный мне случай использования.

Я также понимаю, что мог бы переопределить прототип с помощью {}, но мой ум лучше работает с этим форматом ;-) пристрелите меня.

/**
 * simple parameter object instantiator
 * @param name
 * @param value
 * @returns
 */
function p(name,value) {
    this.name = name;
    this.value = value;
    return Object.freeze(this);
}
/**
 * EnumFieldSegmentBase
 */
function EnumFieldSegmentBase() {
    this.fieldType = "STRING";
}
function dummyregex() {
}
dummyregex.prototype.test = function(str) {
    if(this.fieldType === "STRING") {
        maxlength = arguments[1];
        return str.length <= maxlength;
    }
    return true;
};

dummyregexposer = new dummyregex();
EnumFieldSegmentBase.prototype.getInputRegex = function() { 
    switch(this.fieldType) {
        case "STRING" :     return dummyregexposer;  
        case "INT":         return /^(\d+)?$/;
        case "DECIMAL2":    return /^\d+(\.\d{1,2}|\d+|\.)?$/;
        case "DECIMAL8":    return /^\d+(\.\d{1,8}|\d+|\.)?$/;
        // boolean is tricky dicky. if its a boolean false, if its a string if its empty 0 or false its  false, otherwise lets see what Boolean produces
        case "BOOLEAN":     return dummyregexposer;
    }
};
EnumFieldSegmentBase.prototype.convertToType = function($input) {
    var val = $input;
    switch(this.fieldType) {
        case "STRING" :         val = $input;break;
        case "INT":         val==""? val=0 :val = parseInt($input);break;
        case "DECIMAL2":    if($input === "" || $input === null) {$input = "0"}if($input.substr(-1) === "."){$input = $input+0};val = new Decimal2($input).toDP(2);break;
        case "DECIMAL8":    if($input === "" || $input === null) {$input = "0"}if($input.substr(-1) === "."){$input = $input+0};val = new Decimal8($input).toDP(8);break;
        // boolean is tricky dicky. if its a boolean false, if its a string if its empty 0 or false its  false, otherwise lets see what Boolean produces
        case "BOOLEAN":     val = (typeof $input == 'boolean' ? $input : (typeof $input === 'string' ? (($input === "false" || $input === "" || $input === "0") ? false : true) : new Boolean($input).valueOf()))  ;break;
    }
    return val;
};
EnumFieldSegmentBase.prototype.convertToString = function($input) {
    var val = $input;
    switch(this.fieldType) {
        case "STRING":      val = $input;break;
        case "INT":         val = $input+"";break;
        case "DECIMAL2":    val = $input.toPrecision(($input.toString().indexOf('.') === -1 ? $input.toString().length+2 : $input.toString().indexOf('.')+2)) ;break;
        case "DECIMAL8":    val = $input.toPrecision(($input.toString().indexOf('.') === -1 ? $input.toString().length+8 : $input.toString().indexOf('.')+8)) ;break;
        case "BOOLEAN":     val = $input ? "true" : "false"  ;break;
    }
    return val;
};
EnumFieldSegmentBase.prototype.compareValue = function($val1,$val2) {
    var val = false;
    switch(this.fieldType) {
        case "STRING":      val = ($val1===$val2);break;
        case "INT":         val = ($val1===$val2);break;
        case "DECIMAL2":    val = ($val1.comparedTo($val2)===0);break;
        case "DECIMAL8":    val = ($val1.comparedTo($val2)===0);break;
        case "BOOLEAN":     val = ($val1===$val2);break;
    }
    return val;
};

/**
 * EnumFieldSegment is an individual segment in the 
 * EnumField
 * @param $array An array consisting of object p
 */
function EnumFieldSegment() {
    for(c=0;c<arguments.length;c++) {
        if(arguments[c] instanceof p) {
            this[arguments[c].name] = arguments[c].value;
        }
    }
    return Object.freeze(this); 
}
EnumFieldSegment.prototype = new EnumFieldSegmentBase();
EnumFieldSegment.prototype.constructor = EnumFieldSegment;


/**
 * Simple enum to show what type of variable a Field type is.
 * @param STRING
 * @param INT
 * @param DECIMAL2
 * @param DECIMAL8
 * @param BOOLEAN
 * 
 */
EnumField = Object.freeze({STRING:      new EnumFieldSegment(new p("fieldType","STRING")), 
                            INT:        new EnumFieldSegment(new p("fieldType","INT")), 
                            DECIMAL2:   new EnumFieldSegment(new p("fieldType","DECIMAL2")), 
                            DECIMAL8:   new EnumFieldSegment(new p("fieldType","DECIMAL8")), 
                            BOOLEAN:    new EnumFieldSegment(new p("fieldType","BOOLEAN"))});
1
ответ дан Tschallacka 26 December 2018 в 06:38
поделиться

Мне кажется, им легко пользоваться. https://stackoverflow.com/a/32245370/4365315

var A = {a:11, b:22}, 
enumA = new TypeHelper(A);

if(enumA.Value === A.b || enumA.Key === "a"){ 
... 
}

var keys = enumA.getAsList();//[object, object]

//set
enumA.setType(22, false);//setType(val, isKey)

enumA.setType("a", true);

enumA.setTypeByIndex(1);

ОБНОВЛЕНИЕ:

Есть мои вспомогательные коды (TypeHelper).

var Helper = {
    isEmpty: function (obj) {
        return !obj || obj === null || obj === undefined || Array.isArray(obj) && obj.length === 0;
    },

    isObject: function (obj) {
        return (typeof obj === 'object');
    },

    sortObjectKeys: function (object) {
        return Object.keys(object)
            .sort(function (a, b) {
                c = a - b;
                return c
            });
    },
    containsItem: function (arr, item) {
        if (arr && Array.isArray(arr)) {
            return arr.indexOf(item) > -1;
        } else {
            return arr === item;
        }
    },

    pushArray: function (arr1, arr2) {
        if (arr1 && arr2 && Array.isArray(arr1)) {
            arr1.push.apply(arr1, Array.isArray(arr2) ? arr2 : [arr2]);
        }
    }
};
function TypeHelper() {
    var _types = arguments[0],
        _defTypeIndex = 0,
        _currentType,
        _value,
        _allKeys = Helper.sortObjectKeys(_types);

    if (arguments.length == 2) {
        _defTypeIndex = arguments[1];
    }

    Object.defineProperties(this, {
        Key: {
            get: function () {
                return _currentType;
            },
            set: function (val) {
                _currentType.setType(val, true);
            },
            enumerable: true
        },
        Value: {
            get: function () {
                return _types[_currentType];
            },
            set: function (val) {
                _value.setType(val, false);
            },
            enumerable: true
        }
    });
    this.getAsList = function (keys) {
        var list = [];
        _allKeys.forEach(function (key, idx, array) {
            if (key && _types[key]) {

                if (!Helper.isEmpty(keys) && Helper.containsItem(keys, key) || Helper.isEmpty(keys)) {
                    var json = {};
                    json.Key = key;
                    json.Value = _types[key];
                    Helper.pushArray(list, json);
                }
            }
        });
        return list;
    };

    this.setType = function (value, isKey) {
        if (!Helper.isEmpty(value)) {
            Object.keys(_types).forEach(function (key, idx, array) {
                if (Helper.isObject(value)) {
                    if (value && value.Key == key) {
                        _currentType = key;
                    }
                } else if (isKey) {
                    if (value && value.toString() == key.toString()) {
                        _currentType = key;
                    }
                } else if (value && value.toString() == _types[key]) {
                    _currentType = key;
                }
            });
        } else {
            this.setDefaultType();
        }
        return isKey ? _types[_currentType] : _currentType;
    };

    this.setTypeByIndex = function (index) {
        for (var i = 0; i < _allKeys.length; i++) {
            if (index === i) {
                _currentType = _allKeys[index];
                break;
            }
        }
    };

    this.setDefaultType = function () {
        this.setTypeByIndex(_defTypeIndex);
    };

    this.setDefaultType();
}

var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var enumA = new TypeHelper(TypeA, 4);

document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");


enumA.setType("200L", false);
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");

enumA.setDefaultType();
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");


enumA.setTypeByIndex(1);
document.writeln("Key = ", enumA.Key,", Value = ", enumA.Value, "<br>");

document.writeln("is equals = ", (enumA.Value == TypeA["2"]));
3
ответ дан Community 26 December 2018 в 06:38
поделиться

Начиная с ES6, вы не можете создавать Enums как таковые, но у вас может быть более элегантный синтаксис, подходящий для автозаполнения кода, по крайней мере для VSCode:

class MyEnum {
  const A = '1'
  const B = '2'
  const C = '3'
}

На плюсе вы можете поместить все, что угодно. хочу внутри const, как и в других ответах. Кроме того, в Node вы можете экспортировать его как часть модуля, сохранив значимое имя.

import { MyEnum } from './my-enum'

console.log(MyEnum.B)

Надеюсь, это поможет.

0
ответ дан CodingNagger 26 December 2018 в 06:38
поделиться

Этот ответ является альтернативным подходом для конкретных обстоятельств. Мне нужен был набор констант битовой маски, основанных на под-значениях атрибута (в случаях, когда значением атрибута является массив или список значений). Он охватывает эквивалент нескольких перекрывающихся перечислений.

Я создал класс для хранения и генерации значений битовой маски. Затем я могу использовать значения псевдо-константной битовой маски таким образом, чтобы проверить, например, присутствует ли зеленый в значении RGB:

if (value & Ez.G) {...}

В моем коде я создаю только один экземпляр этого класса. Кажется, нет простого способа сделать это без создания хотя бы одного экземпляра класса. Вот объявление класса и код генерации значения битовой маски:

class Ez {
constructor() {
    let rgba = ["R", "G", "B", "A"];
    let rgbm = rgba.slice();
    rgbm.push("M");              // for feColorMatrix values attribute
    this.createValues(rgba);
    this.createValues(["H", "S", "L"]);
    this.createValues([rgba, rgbm]);
    this.createValues([attX, attY, attW, attH]);
}
createValues(a) {                // a for array
    let i, j;
    if (isA(a[0])) {             // max 2 dimensions
        let k = 1;
        for (i of a[0]) {
            for (j of a[1]) {
                this[i + j] = k;
                k *= 2;
            }
        }
    }
    else {                       // 1D array is simple loop
        for (i = 0, j = 1; i < a.length; i++, j *= 2)
            this[a[i]] = j;
   }
}

2D-массив предназначен для атрибута значений SVG feColorMatrix, который представляет собой матрицу RGBA 4x5 от RGBAM, где M - множитель. Результирующие свойства Ez - это Ez.RR, Ez.RG и т. Д.

0
ответ дан jamess 26 December 2018 в 06:38
поделиться

UPDATE

Спасибо всем за поддержку, но я не думаю, что мой ответ ниже - это лучший способ написания перечислений в JavaScript. См. более подробную информацию в моем блоге: Enums in JavaScript.


Оповещение по имени уже возможно:

if (currentColor == my.namespace.ColorEnum.RED) {
   // alert name of currentColor (RED: 0)
   var col = my.namespace.ColorEnum;
   for (var name in col) {
     if (col[name] == col.RED)
       alert(name);
   }
}

В качестве альтернативы, вы можете сделать значения объектами, так что вы можете получить торт и съесть его тоже:

var SIZE = {
  SMALL : {value: 0, name: "Small", code: "S"}, 
  MEDIUM: {value: 1, name: "Medium", code: "M"}, 
  LARGE : {value: 2, name: "Large", code: "L"}
};

var currentSize = SIZE.MEDIUM;
if (currentSize == SIZE.MEDIUM) {
  // this alerts: "1: Medium"
  alert(currentSize.value + ": " + currentSize.name);
}

В JavaScript, поскольку это динамический язык, можно даже добавить значения перечисления в набор позже:

// Add EXTRALARGE size
SIZE.EXTRALARGE = {value: 3, name: "Extra Large", code: "XL"};

Помните, что поля перечисления (значение, имя и код в этом примере) не нужны для проверки идентичности и находятся там только для удобства. Также имя самого свойства size не обязательно должно быть жестко закодировано, оно может быть задано динамически. Таким образом, если вы знаете только имя для нового значения перечисления, вы можете добавить его без проблем:

// Add 'Extra Large' size, only knowing it's name
var name = "Extra Large";
SIZE[name] = {value: -1, name: name, code: "?"};

Конечно, это означает, что некоторые предположения больше не могут быть сделаны (например, что значение представляет правильный порядок для размера).

Помните, что в JavaScript объект - это то же самое, что карта или хэш-таблица. Набор пар имя-значение. Вы можете перебирать их или иным образом манипулировать ими, не зная о них ничего заранее.

Пример

for (var sz in SIZE) {
  // sz will be the names of the objects in SIZE, so
  // 'SMALL', 'MEDIUM', 'LARGE', 'EXTRALARGE'
  var size = SIZE[sz]; // Get the object mapped to the name in sz
  for (var prop in size) {
    // Get all the properties of the size object, iterates over
    // 'value', 'name' and 'code'. You can inspect everything this way.        
  }
} 

И кстати, если вы интересуетесь пространствами имен, вам стоит взглянуть на мое решение для простого, но мощного управления пространствами имен и зависимостями для JavaScript: Пакеты JS

493
ответ дан 22 November 2019 в 20:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: