es6-mixin
Version:
Minimalist mixin helper designed to be used with ES6 (ES2015) classes.
140 lines (107 loc) • 6.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.mixin = mixin;
exports.mix = mix;
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Converts an object to an array of pairs, in the form of an array of tuples
* where index 0 is the key and index 1 is the value. This include both
* enumerable and non-enumerable properties.
* @param {object} object Object for which to get pairs
* @returns {[string, *][]} Array containing object pairs
*/
function entries(object) {
return Object.getOwnPropertyNames(object).map(function (key) {
return [key, object[key]];
});
}
/**
* Generic mixin superclass. This class is intended to be extended by actual
* mixins.
*/
var Mixin = exports.Mixin = function () {
function Mixin() {
_classCallCheck(this, Mixin);
}
_createClass(Mixin, null, [{
key: 'mixin',
/**
* Mixes in this class's methods into an existing object.
* @param {object} [target={}] Any object to mix this class's methods into
* @param {function} [MixedIn=this] Constructor to be mixed in
* @param {...*} [args] Arguments to pass to the mixed in constructor, if any
* @return {object} The original target object, mutated
*/
value: function mixin() {
var target = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var MixedIn = arguments.length <= 1 || arguments[1] === undefined ? this : arguments[1];
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
var instance = new (Function.prototype.bind.apply(MixedIn, [null].concat(args)))();
// Get all the methods from this class, bind them to the instance, and copy
// them to the target object.
entries(MixedIn.prototype).filter(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2);
var methodName = _ref2[0];
var method = _ref2[1];
return typeof method === 'function' && methodName !== 'constructor';
}).forEach(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2);
var methodName = _ref4[0];
var method = _ref4[1];
return target[methodName] = method.bind(instance);
});
return target;
}
}]);
return Mixin;
}();
/**
* Mixes in this class's methods into an existing object.
* @param {object} [target={}] Any object to mix this class's methods into
* @param {function} [MixedIn=Mixin] Constructor to be mixed in
* @param {...*} [args] Arguments to pass to the mixed in constructor, if any
* @return {object} The original target object, mutated
*/
function mixin() {
var target = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var MixedIn = arguments.length <= 1 || arguments[1] === undefined ? Mixin : arguments[1];
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
args[_key2 - 2] = arguments[_key2];
}
return Mixin.mixin.apply(Mixin, [target, MixedIn].concat(args));
}
/**
* Create a subclass of a constructor and mix 1 or many mixin into it.
* @param {function} SuperClass Class that will be used as super-class
* @param {...function} mixins Mixins to add
* @return {function} A new anonymous class that extends `SuperClass` and has all `mixins` mixed in
*/
function mix(SuperClass) {
for (var _len3 = arguments.length, mixins = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
mixins[_key3 - 1] = arguments[_key3];
}
return function (_SuperClass) {
_inherits(_class, _SuperClass);
function _class() {
var _Object$getPrototypeO;
_classCallCheck(this, _class);
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
var _this = _possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(_class)).call.apply(_Object$getPrototypeO, [this].concat(args)));
mixins.forEach(function (Mixedin) {
return mixin(_this, Mixedin);
});
return _this;
}
return _class;
}(SuperClass);
}