proteus
Version:
A declarative way of creating objects, properties, and classes in ES5 JavaScript
123 lines (104 loc) • 3.32 kB
JavaScript
var APSlice = Array.prototype.slice,
hasOwnProp = Object.prototype.hasOwnProperty
;
function slice (list, offset, end) {
return APSlice.call(list, offset || 0, end || list.length);
}
function enumerate () {
return slice(arguments).reduce(function (o, k, idx) {
o[k] = idx + 1;
return o;
}, {});
}
function map () {
return slice(arguments).reduce(function (acc, cur, idx) {
var obj = acc[0],
key = acc[1]
;
if (idx % 2 && key !== null) {
obj[key] = cur;
}
else {
acc[1] = cur;
}
return acc;
}, [{}])[0];
}
/**
* @method copyOwnProperties
* @param {Boolean} hidden copy hidden properties, default is 'false'
* @param {Boolean} overwrite overwrite properties already defined on
* receiver, default is true
* @param {object} supplier
* @param {object} receiver
*/
function copyOwnProperties (hidden, overwrite, supplier, receiver) {
var hasOwn = hasOwnProp,
getOwnDesc = Object.getOwnPropertyDescriptor,
names, spec, len, i, key,
configurable
;
if (!supplier) { return; }
hidden = hidden === true ? true : false;
overwrite = overwrite === false ? false : true;
names = Object.getOwnPropertyNames(supplier);
for (i = 0, len = names.length; i < len; i++) {
key = names[i];
spec = getOwnDesc(supplier, key);
rspec = getOwnDesc(receiver, key);
configurable = !rspec || rspec.configurable;
if ((spec.enumerable || hidden) &&
(!hasOwn.call(receiver, key) || (overwrite && configurable))
) {
Object.defineProperty(receiver, key, spec);
}
}
return receiver;
}
function _copy (fn) {
var args = slice(arguments, 1),
receiver = args.shift(),
len = args.length,
i = 0
;
for (; i < len; i++) {
fn.apply(this, [args[i], receiver]);
}
return receiver;
}
var copyAllProperties = copyOwnProperties.bind(this, true, true);
var applyProperties = copyOwnProperties.bind(this, false, false);
var applyAllProperties = copyOwnProperties.bind(this, true, false);
module.exports = {
/**
* Re-usable object
* @property EMPTY
* @type {Object}
* @readOnly
*/
EMPTY: {},
/**
* @method slice
* @param {Array} list Array, or Array-like object to slice
* @param {Integer} [offset=0] Where to start slicing
* @param {Integer} [end=list.length] Where to stop slicing
* @return {Array}
*/
slice: slice,
/**
* @method enumerate
* @param {Array} list Array, or Array-like object to slice
* @param {Integer} [offset=0] Where to start slicing
* @param {Integer} [end=list.length] Where to stop slicing
* @return {Array}
*/
enumerate: enumerate,
map: map,
copyAllProperties: copyAllProperties,
applyProperties: applyProperties,
applyAllProperties: applyAllProperties,
merge: _copy.bind(this, copyOwnProperties.bind(this, false, true)),
mergeAll: _copy.bind(this, copyAllProperties),
apply: _copy.bind(this, applyProperties),
applyAll: _copy.bind(this, applyAllProperties)
};