[6a3a178] | 1 | /*!
|
---|
| 2 | * static-extend <https://github.com/jonschlinkert/static-extend>
|
---|
| 3 | *
|
---|
| 4 | * Copyright (c) 2016, Jon Schlinkert.
|
---|
| 5 | * Licensed under the MIT License.
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | 'use strict';
|
---|
| 9 |
|
---|
| 10 | var copy = require('object-copy');
|
---|
| 11 | var define = require('define-property');
|
---|
| 12 | var util = require('util');
|
---|
| 13 |
|
---|
| 14 | /**
|
---|
| 15 | * Returns a function for extending the static properties,
|
---|
| 16 | * prototype properties, and descriptors from the `Parent`
|
---|
| 17 | * constructor onto `Child` constructors.
|
---|
| 18 | *
|
---|
| 19 | * ```js
|
---|
| 20 | * var extend = require('static-extend');
|
---|
| 21 | * Parent.extend = extend(Parent);
|
---|
| 22 | *
|
---|
| 23 | * // optionally pass a custom merge function as the second arg
|
---|
| 24 | * Parent.extend = extend(Parent, function(Child) {
|
---|
| 25 | * Child.prototype.mixin = function(key, val) {
|
---|
| 26 | * Child.prototype[key] = val;
|
---|
| 27 | * };
|
---|
| 28 | * });
|
---|
| 29 | *
|
---|
| 30 | * // extend "child" constructors
|
---|
| 31 | * Parent.extend(Child);
|
---|
| 32 | *
|
---|
| 33 | * // optionally define prototype methods as the second arg
|
---|
| 34 | * Parent.extend(Child, {
|
---|
| 35 | * foo: function() {},
|
---|
| 36 | * bar: function() {}
|
---|
| 37 | * });
|
---|
| 38 | * ```
|
---|
| 39 | * @param {Function} `Parent` Parent ctor
|
---|
| 40 | * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype.
|
---|
| 41 | * @param {Function} `Child` Child ctor
|
---|
| 42 | * @param {Object} `proto` Optionally pass additional prototype properties to inherit.
|
---|
| 43 | * @return {Object}
|
---|
| 44 | * @api public
|
---|
| 45 | */
|
---|
| 46 |
|
---|
| 47 | function extend(Parent, extendFn) {
|
---|
| 48 | if (typeof Parent !== 'function') {
|
---|
| 49 | throw new TypeError('expected Parent to be a function.');
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | return function(Ctor, proto) {
|
---|
| 53 | if (typeof Ctor !== 'function') {
|
---|
| 54 | throw new TypeError('expected Ctor to be a function.');
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | util.inherits(Ctor, Parent);
|
---|
| 58 | copy(Ctor, Parent);
|
---|
| 59 |
|
---|
| 60 | // proto can be null or a plain object
|
---|
| 61 | if (typeof proto === 'object') {
|
---|
| 62 | var obj = Object.create(proto);
|
---|
| 63 |
|
---|
| 64 | for (var k in obj) {
|
---|
| 65 | Ctor.prototype[k] = obj[k];
|
---|
| 66 | }
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | // keep a reference to the parent prototype
|
---|
| 70 | define(Ctor.prototype, '_parent_', {
|
---|
| 71 | configurable: true,
|
---|
| 72 | set: function() {},
|
---|
| 73 | get: function() {
|
---|
| 74 | return Parent.prototype;
|
---|
| 75 | }
|
---|
| 76 | });
|
---|
| 77 |
|
---|
| 78 | if (typeof extendFn === 'function') {
|
---|
| 79 | extendFn(Ctor, Parent);
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | Ctor.extend = extend(Ctor, extendFn);
|
---|
| 83 | };
|
---|
| 84 | };
|
---|
| 85 |
|
---|
| 86 | /**
|
---|
| 87 | * Expose `extend`
|
---|
| 88 | */
|
---|
| 89 |
|
---|
| 90 | module.exports = extend;
|
---|