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')
JSON.stringify(red).should.equal('{"hex":"#F00"}')
})
it('Test: Color.BLUE', () => {
let blue = Color.BLUE
chai.assert.isNotNull(blue)
blue.getHex().should.equal('#0F0')
JSON.stringify(blue).should.equal('{"hex":"#0F0"}')
})
it('Test: Color.GREEN', () => {
let green = Color.GREEN
chai.assert.isNotNull(green)
green.getHex().should.equal('#00F')
JSON.stringify(green).should.equal('{"hex":"#00F"}')
})
it('Test: Color.YELLOW', () => {
let yellow = Color.YELLOW
chai.assert.isUndefined(yellow)
})
})
mocha.run()
}
class Enum {
constructor(...values) {
this.__values = []
const [first, ...rest] = values
const hasOne = rest.length === 0
const isArray = Array.isArray(first)
const args = hasOne ? (isArray ? first : Object.keys(first)) : values
args.forEach((name, index) => {
this.__createValue({
name,
index,
props: hasOne && !isArray ? first[name] : null
})
})
Object.freeze(this)
}
values() {
return this.__values
}
__createValue({ name, index, props }) {
const value = Object.create(Enum.__prototype(props))
Object.defineProperties(value, Enum.__defineReservedProps({
name,
index
}))
if (props) {
Object.defineProperties(value, Enum.__defineAccessors(props))
}
Object.defineProperty(this, name, {
value: Object.freeze(value),
writable: false
})
this.__values.push(this[name])
}
}
Enum.__prototype = (props) => ({
toJSON() {
return props;
},
toString() {
return JSON.stringify(props);
}
});
Enum.__defineReservedProps = ({ name, index }) => ({
name: {
value: Symbol(name),
writable: false
},
ordinal: {
value: index,
writable: false
}
})
Enum.__defineAccessors = (props) =>
Object.entries(props).reduce((acc, [prop, val]) => ({
...acc,
[prop]: {
value: val,
writable: false
},
[`get${Enum.__capitalize(prop)}`]: {
get: () => function() {
return this[prop]
}
}
}), {})
Enum.__capitalize = (str) => 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>
<div id="mocha"></div>
JSON.stringify()
一起使用此枚举。不能序列化/反序列化Symbol
。 - le_m