JavaScript. Подробное руководство, 6-е издание, стр. 117

В языке С и его производных типы-перечисления объявляются с помощью ключевого слова

<b>enum</b>
. В ECMAScript 5
<b>enum</b>
- это зарезервированное (но не используемое) слово, оставленное на тот случай, если когда-нибудь в JavaScript будут реализованы встроенные типы-перечисления. А пока в примере 9.7 демонстрируется, как можно определить собственный тип-перечисление на языке JavaScript. Обратите внимание, что здесь используется функция
<b>inherit()</b>
из примера 6.1.

Пример 9.7 содержит единственную функцию

<b>enumeration().</b>
Однако она не является конструктором: она не определяет класс с именем «enumeration». Но она является фабричной функцией: при каждом вызове она создает и возвращает новый класс. Ниже показано, как ее можно использовать:

<b>// Создать новый класс Coin с четырьмя возможными значениями:</b>

<b>// Coin.Penny, Coin.Nickel и т. д.</b>

<b>var Coin = enumeration({Penny: 1, Nickel:5, Dime:10, Quarter:25});</b>

<b>var c = Coin.Dime; // Это экземпляр нового класса</b>

<b>с instanceof Coin // =&gt; true: instanceof работает</b>

<b>c.constructor == Coin // =&gt; true: свойство constructor работает</b>

<b>Coin.Quarter + 3*Coin.Nickel // =&gt; 40: значения преобразуются в числа</b>

<b>Coin.Dime == 10 // =&gt; true: еще одно преобразование в число</b>

<b>Coin.Dime &gt; Coin.Nickel // =&gt; true: операторы отношения работают</b>

<b>String(Coin.Dime) + &quot;:&quot; + Coin.Dime // =&gt; &quot;Dime:10&quot;: преобразов, в строку</b>

Цель этого примера состоит в том, чтобы продемонстрировать, что классы в языке JavaScript являются более гибкими и динамичными, чем статические классы в таких языках, как C++ и Java.

Пример 9.7 Типы-перечисления в JavaScript

<b>// Эта функция создает новый тип-перечисление. Объект в аргументе определяет</b>

<b>// имена и значения каждого экземпляра класса. Возвращает функцию-конструктор,</b>

<b>// идентифицирующую новый класс. Отметьте, однако, что конструктор возбуждает</b>

<b>// исключение: его нельзя использовать для создания новых экземпляров типа.</b>

<b>// Возвращаемый конструктор имеет свойства, которые отображают имена в значения,</b>

<b>// а также массив значений values и функцию foreach() для выполнения итераций</b>

<b>function enumeration(namesToValues) {</b>

<b>  // Фиктивный конструктор, который будет использоваться как </b>

<b>  // возвращаемое значение.</b>

<b>  var enumeration = function() { throw &quot;Нельзя создать экземпляр класса” +</b>

<b>                            Enumeration&quot;; };</b>

<b>  // Перечислимые значения наследуют объект this, </b>

<b>  var proto = enumeration.prototype = {</b>

<b>    constructor: enumeration, // Идентификатор типа</b>

<b>    toString: function() { return this.name; }, // Возвращает имя </b>

<b>    valueOf: function() { return this.value; }, // Возвращает значение </b>

<b>    toJSON: function() { return this.name; } // Для сериализации</b>

<b>  };</b>

<b>  enumeration.values = []; // Массив перечислимых объектов-значений</b>

<b>  // Теперь создать экземпляры нового типа.</b>

<b>  for(name in namesToValues) { // Для каждого значения</b>

<b>    var е = inherit(proto); // Создать объект для его представления</b>

<b>    e.name = name; // Дать ему имя</b>

<b>    е.value = namesToValues[name]; // И значение</b>

<b>    enumeration[name] = е; // Сделать свойством конструктора</b>

<b>    enumeration.values.push(e); // И сохранить в массиве values</b>

<b>  }</b>

<b>  // Метод класса для обхода экземпляров класса в цикле</b>

<b>  enumeration.foreach = function(f,с) {</b>

<b>    for(var і = 0; і &lt; this.values.length; i++) f.call(c,this.values[i]);</b>

<b>  };</b>

<b>  // Вернуть конструктор, идентифицирующий новый тип</b>

<b>  return enumeration;</b>

<b>}</b>

Типичным начальным примером использования типов-перечислений может служить реализация перечисления для представления колоды игральных карт. Пример 9.8 использует функцию enumeration) именно для этого, а также определяет классы для представления карт и колод карт. [16]

Пример 9.8. Представление игральных карт в виде типов-перечислений

<b>// Определение класса для представления игральной карты</b>

<b>function Card(suit, rank) {</b>

<b>  this.suit = suit; // Каждая карта имеет масть</b>

<b>  this.rank = rank; // и значение</b>

<b>}</b>

<b>// Следующие типы-перечисления определяют возможные масти и значения карт</b>