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;
|
---|