enumerationjs
Version:
Java-like super flexible enums ! Move the logic.
252 lines (172 loc) • 11.2 kB
Markdown
<a name="top"></a>
# enumerationjs : Java-like enum for javascript/coffeescript



[](https://github.com/sveinburne/enumerationjs)
*Straightforward though very flexible solution addressing the unimplemented `enum` keyword.*
**KEY POINTS**
- *functionalities*
ⓘ An **enum type** `MyEnum`
→ is `instanceof` the `Enumeration` constructor
→ is **immutable**
→ can be inherited ([JS](JS.GUIDE.MD#extendyourenumerationwithprototypeinheritance) | [COFFEE](COFFEE.GUIDE.MD#extendyourenumerationwithprototypeinheritance))
→ `Object.keys(MyEnum)` is `["SOME_CONST1","SOME_CONST2"]`
ⓘ An **enum constant** `MyEnum.SOME_CONSTANT1`
→ is `instanceof` `MyEnum`
→ is **immutable**
→ can **inherit a prototype shared across `MyEnum` constants** ([JS](JS.GUIDE.MD#aprototypeforenumconstants) | [COFFEE](COFFEE.GUIDE.MD#aprototypeforenumconstants))
→ can have **its own specific properties** ([JS](JS.GUIDE.MD#useofstructureddescriptors) | [COFFEE](COFFEE.GUIDE.MD#useofstructureddescriptors))
✓ Allow easy refactoring, avoiding the `if else` mess ([JS](JS.GUIDE.MD#refactoring) | [COFFEE](COFFEE.GUIDE.MD#refactoring))
✓ Lightweight **deserialization** with `MyEnum.from(identifier)` and **serialization** with `MyEnum.ENUM_CONST.id()`
- *integration*
✓ **Rock solid** jasmine specified tests.
✓ Fully **CommonJS** and **AMD** compliant through a **Universal Module Definition** | since v1.3.0
✓ Available for **npm**, **bower** and **Meteor**, see the [packages section](#packages)
ⓘ Depends on **underscore**, but you can use **lodash**, tested. See [this section](#dependencies) for more infos.
⚠ The package will work with ecmascript3 standards (IE<=8) but immutability is provided through ecmascript5 standard, see [this section](#ecmascript)
**EXAMPLES**
> [→ COFFEE.GUIDE.MD](COFFEE.GUIDE.MD#top) for coffescript devs
> [→ JS.GUIDE.MD](JS.GUIDE.MD#top) for js devs
**DOWNLOAD**
<a name="bundled"></a>
> ❗ Shipped with **underscore**, ready-to-use
> → [COMMENTED BUNDLE ~ 62K](https://raw.githubusercontent.com/sveinburne/enumeration.js/master/dist/Enumeration.bd.js) | [MINIFIED BUNDLE ~ 31K](https://raw.githubusercontent.com/sveinburne/enumeration.js/master/dist/Enumeration.bd.min.js)
> ⚠ Assuming you can provide **underscore**, either through AMD or global variable `_`
> → [UNDERSCORE-READY COMMENTED ~ 9.4K](https://raw.githubusercontent.com/sveinburne/enumeration.js/master/dist/Enumeration.js) | [UNDERSCORE-READY MINIFIED ~ 5.3K](https://raw.githubusercontent.com/sveinburne/enumeration.js/master/dist/Enumeration.min.js)
> ⚠ Assuming you can provide **lodash**, either through AMD or global variable `_`. Read [this section](#forlodashusers) first
> → [LODASH-READY COMMENTED ~ 9.4K](https://raw.githubusercontent.com/sveinburne/enumeration.js/lodashv2/dist/Enumeration.js) | [LODASH-READY MINIFIED ~ 5.3K](https://raw.githubusercontent.com/sveinburne/enumeration.js/lodashv2/dist/Enumeration.min.js)
<a name="packages"></a>
**PACKAGES**
> `npm install enumerationjs`
> `bower install enumerationjs`
> `meteor add sveinburne:enumerationjs`
<a name="toc"></a>
**TABLE OF CONTENTS**
1\. [AMD](#amd)
1.1\. [UMD Behaviour](#umdbehaviour)
1.2\. [Requirejs + lodash](#requirejs+lodash)
2\. [Quick api overview](#quickapioverview)
2.1\. [Enumeration.constructor](#enumeration.constructor)
2.2\. [Enumeration constant](#enumerationconstant)
2.3\. [Enumeration instance aka enum type](#enumerationinstanceakaenumtype)
2.4\. [Enumeration object](#enumerationobject)
2.5\. [More examples](#moreexamples)
3\. [Ecmascript compatibility](#ecmascriptcompatibility)
4\. [Dependencies](#dependencies)
4.1\. [Underscore](#underscore)
4.2\. [For lodash users](#forlodashusers)
5\. [Changelog](#changelog)
<a name="amd"></a>
### 1\. AMD
> dependency name is "enumerationjs"
<a name="umdbehaviour"></a>
#### 1.1\. UMD Behaviour
If `_` is defined global, the **enumeration.js** will be defined with **no dependency**.
Otherwise, it will call `define` with a dependency on **underscore**
<a name="requirejs+lodash"></a>
#### 1.2\. Requirejs + lodash
you can map *underscore* to *lodash* to avoid an extra dependency easily :
require.config({
map: {
'*': {
'underscore': 'lodash'
}
}
})
<a name="quickapioverview"></a>
### 2\. Quick api overview
<a name="enumeration.constructor"></a>
#### 2.1\. Enumeration.constructor
You can instantiate an enum type with the provided `Enumeration` constructor. It will take three arguments :
- `MyEnum` : the name of this enumeration, must be unique amongst other Enumeration instances.
- `enumConstants` : an object containing the set of enum constants. Each key is the enum constant name and each value is a descriptor that can either be ...
* a **raw descriptor** i.e. a unique identifier of type string or number ([JS](JS.GUIDE.MD#basicusagewithrawdescriptors) | [COFFEE](COFFEE.GUIDE.MD#basicusagewithrawdescriptors))
* a **structured descriptor** i.e. a plain object ([JS](JS.GUIDE.MD#useofstructureddescriptors) | [COFFEE](COFFEE.GUIDE.MD#useofstructureddescriptors))
- `prototype` : [optional] a prototype all the enum constants will inherit ([JS](JS.GUIDE.MD#aprototypeforenumconstants) | [COFFEE](COFFEE.GUIDE.MD#aprototypeforenumconstants))
<a name="enumerationconstant"></a>
#### 2.2\. Enumeration constant
Each **enum constant** will have the following methods :
- `key()` : retrieve the key (`SOME_ENUM_CONST` for example)
- `id()` : retrieve the identifier (`1000` for example)
- `type()` : retrieve the enum type,`MyEnum` Enumeration constructor's argument
- `describe()` : return a string of the form 'key:id', useful for logging/debugging
...plus the properties provided at instantiation time (inherited from `prototype` and provided by descriptors)
<a name="enumerationinstanceakaenumtype"></a>
#### 2.3\. Enumeration instance aka enum type
- `from(id,throwOnFailure=false)` : retrieve the enum constant that matches given `id`. [optional] throwOnFailure, default to false, throws an error when no id match.
- `pretty()` : give a pretty description of this enum type and all its constants, useful for logging/debugging
- `()` : shortcut for `pretty()`
<a name="enumerationobject"></a>
#### 2.4\. Enumeration object
- `Enumeration.types()` : returns an array containing the `MyEnum` for each enum type.
<a name="moreexamples"></a>
#### 2.5\. More examples
> [→ COFFEE.GUIDE.MD](COFFEE.GUIDE.MD#top) for coffescript devs
> [→ JS.GUIDE.MD](JS.GUIDE.MD#top) for js devs
<a name="ecmascript"></a>
<a name="ecmascriptcompatibility"></a>
### 3\. Ecmascript compatibility
> ECMA-262 5th edition was published on December 3, 2009
Among those specifications, the following methods must be available to have control over immutability:
```javascript
Object.defineProperty(object,property,propertyDescriptor)
Object.freeze(object)
```
These methods prevent user from mistakenly modify any property from the enum type and its bound constants :
**any attempt to write a read-only property [in 'strict mode' will throw an error](http://www.w3schools.com/js/js_strict.asp)**, ignored otherwise.
**any attempt to reconfigure a non-configurable property [in 'strict mode' will throw an error](http://www.w3schools.com/js/js_strict.asp)**, ignored otherwise.
For older browser, those methods have fallbacks so no exception will show up, however the write permissions will be ignored.
<a name="dependencies"></a>
### 4\. Dependencies
<a name="underscore"></a>
#### 4.1\. Underscore
Relies on underscore >=1.4.
**NB** : On version 1.2 I switched to **lodash** for its optimizations and improvements, but on the other hand **underscore** appeared lighter for the bundled version,
plus it's heavily used by meteor.
<a name="forlodashusers"></a>
#### 4.2\. For lodash users
**Downloaded version**
The latest release has mirror branches with lodash required instead of underscore. Here are the travis build for each of these branches :
**lodash v2 (last)** : 
**lodash v3 (last)** : 
For either cases, you can download the appropriate versions here (assuming you can provide the **lodash** dependency of course):
> → [LODASH-READY COMMENTED ~ 8.1K](https://raw.githubusercontent.com/sveinburne/enumeration.js/lodashv2/dist/Enumeration.js) | [LODASH-READY MINIFIED ~ 4.4K](https://raw.githubusercontent.com/sveinburne/enumeration.js/lodashv2/dist/Enumeration.min.js)
>
ⓘ By loading lodash in a non-AMD context, a global `_` variable will be defined and it will work seamlessly
ⓘ By loading lodash in an AMD context, enumeratoinjs will `require("lodash")`
**Dependency managers version**
>
ⓘ With **bower**, it seems possible by overriding underscore dependency, see [this so thread](http://stackoverflow.com/questions/24231184/bower-override-dependency)
⚠ With **npm**, you cannot override dependencies. It is however still possible to shim `_` globally with [browserify](https://gist.github.com/malte-wessel/8a295bc604c4a0d0dbe1).
<a name="changelog"></a>
### 5\. Changelog
NB : minor doc fixes are not listed above
**v1.3.11**
- Official lodash support
**v1.3.10**
- Hot bugfix with `function create is not a constructor`
**v1.3.8**
- Fixed underscore minimum version to 1.4, their changelog didn't mention `_.object` method so I tought it to be shipped from the beginning
- Partial support for non ECMA5 engines
- Replaced `__proto__` direct assignments with custom `createObject` to allow full integration with old browsers
- Performed check over `Object.defineProperty` and `Object.create` with IE8 and lower check support
**v1.3.7**
- Added changelog
**v1.3.6**
- Fixed bug with describe() method when descriptors are structured
**v1.3.4**
- Meteor support
- Added Enumeration.types() as an alias to Enumeration.list() to be semantically consistent
**v1.3.2**
- Enhanced semantic consistency
**v1.3.0**
- UML loader, AMD compliant
- replaced lodash with underscore
**v1.2.2**
- Fixed MyEnum() function bug
**v1.2.0**
- Replaced underscore with lodash
**v1.0**
- First release
**↑ Back to [TABLE OF CONTENTS](#toc)**