在JavaScript中, 通常我们都会用到枚举和常量池, 那该如何优雅的定义常量池呢?
// 定义全局默认格式化函数
let _defaultFormatter = function (value) {
return this.getLabel(value);
};
/**
* @class Constant 定义枚举类
*
* @param {Object | Array} map 枚举对象或数组
* @param {Function} formatter 自定义格式化函数
*/
export default class Constant {
constructor (map, formatter) {
// 只接收对象或数组参数
if (!(map instanceof Object)) {
throw new Error('The parameter should be an object or array.');
}
const self = this;
this._keys = Object.keys(map);
this._values = {};
this.LABEL = {};
this._options = {};
this._keys.forEach((key) => {
const m = map[key];
// 接收整数或字符串
if (typeof m === 'number' || typeof m === 'string') {
self[key] = m;
self.LABEL[key] = m;
} else if ((m instanceof Array)) {
// 数组 [1, 'Label']
self[key] = m[0];
self.LABEL[key] = m[1];
self._options[self[key]] = {};
if (m[2] && typeof m[2] === 'object') {
// get other attrs
Object.keys(m[2]).forEach(attr => {
if (attr !== 'value' && attr !== 'label') {
self._options[self[key]][attr] = m[2][attr];
}
});
}
} else if ((m instanceof Object)) {
// 对象 {value: 1, label: 'Label'}
self[key] = m.value;
self.LABEL[key] = m.label;
self._options[self[key]] = {};
// get other attrs
Object.keys(m).forEach(attr => {
if (attr !== 'value' && attr !== 'label') {
self._options[self[key]][attr] = m[attr];
}
});
} else {
throw new Error('The attribute\'s value should be an object, array, number or string.');
}
this._values[self[key]] = self.LABEL[key];
});
// custom formatter
this.formatter = typeof formatter === 'function' ? formatter.bind(self) : Constant.defaultFormatter.bind(self);
}
// [[[ formatter setter and getter
static get defaultFormatter () {
return _defaultFormatter;
}
static set defaultFormatter (fn) {
_defaultFormatter = fn;
}
// ]]]
/**
* 通过value获取Label
* @param value
* @returns {*}
*/
getLabel (value) {
return this._values[value] || '';
}
/**
* 获取额外参数项
* @param value
* @returns {*|{}}
*/
getOptions (value) {
// console.log(value, this._options);
return this._options[value] || {};
}
/**
* 校验value合法性
* @param value
* @returns {boolean}
*/
isValid (value) {
// console.log(Object.keys(this._values), value);
return Object.keys(this._values).map(o => +o).indexOf(value) !== -1;
}
/**
* 以数组方式返回
* @returns {{label: *, value: *, key: string}[]}
*/
toArray () {
return this._keys.filter(key => {
// 过滤小于1的枚举值
const val = this[key];
return (typeof val === 'string') || val >= 0;
}).map(key => {
return {
key,
value: this[key],
label: this.LABEL[key],
...this._options[this[key]]
};
});
}
}
// 使用方式
const level = new Constant([
{ key: 'error', value: 1, label: '错误', arg1, arg2, ... },
{ key: 'warn', value: 2, label: '警告', arg1, arg2, ... },
{ value: 3, label: '正常' }
]);
const level = new Constant({
error: [1, '错误', [argsObject]],
warn: [2, '警告', [argsObject]],
info: [3, '正常', [argsObject]],
}, [function(value) formatter]);
level.error; // 1
level.LABEL.error; // 错误
level.getLabel([value]); // 菜单
level.getOptions(1); // 额外信息 => argsObject
level.toArray(); // [{ key: 'error', value: 1, label: '错误', arg1, arg2, ... }, { key: 'warn', value: 2, label: '警告', arg1, arg2, ... }, ...]
评论