| /*! |
| * static-extend <https://github.com/jonschlinkert/static-extend> |
| * |
| * Copyright (c) 2016, Jon Schlinkert. |
| * Licensed under the MIT License. |
| */ |
| |
| 'use strict'; |
| |
| var copy = require('object-copy'); |
| var define = require('define-property'); |
| var util = require('util'); |
| |
| /** |
| * Returns a function for extending the static properties, |
| * prototype properties, and descriptors from the `Parent` |
| * constructor onto `Child` constructors. |
| * |
| * ```js |
| * var extend = require('static-extend'); |
| * Parent.extend = extend(Parent); |
| * |
| * // optionally pass a custom merge function as the second arg |
| * Parent.extend = extend(Parent, function(Child) { |
| * Child.prototype.mixin = function(key, val) { |
| * Child.prototype[key] = val; |
| * }; |
| * }); |
| * |
| * // extend "child" constructors |
| * Parent.extend(Child); |
| * |
| * // optionally define prototype methods as the second arg |
| * Parent.extend(Child, { |
| * foo: function() {}, |
| * bar: function() {} |
| * }); |
| * ``` |
| * @param {Function} `Parent` Parent ctor |
| * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. |
| * @param {Function} `Child` Child ctor |
| * @param {Object} `proto` Optionally pass additional prototype properties to inherit. |
| * @return {Object} |
| * @api public |
| */ |
| |
| function extend(Parent, extendFn) { |
| if (typeof Parent !== 'function') { |
| throw new TypeError('expected Parent to be a function.'); |
| } |
| |
| return function(Ctor, proto) { |
| if (typeof Ctor !== 'function') { |
| throw new TypeError('expected Ctor to be a function.'); |
| } |
| |
| util.inherits(Ctor, Parent); |
| copy(Ctor, Parent); |
| |
| // proto can be null or a plain object |
| if (typeof proto === 'object') { |
| var obj = Object.create(proto); |
| |
| for (var k in obj) { |
| Ctor.prototype[k] = obj[k]; |
| } |
| } |
| |
| // keep a reference to the parent prototype |
| define(Ctor.prototype, '_parent_', { |
| configurable: true, |
| set: function() {}, |
| get: function() { |
| return Parent.prototype; |
| } |
| }); |
| |
| if (typeof extendFn === 'function') { |
| extendFn(Ctor, Parent); |
| } |
| |
| Ctor.extend = extend(Ctor, extendFn); |
| }; |
| }; |
| |
| /** |
| * Expose `extend` |
| */ |
| |
| module.exports = extend; |