-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathconstructor.js
More file actions
156 lines (123 loc) · 4.13 KB
/
constructor.js
File metadata and controls
156 lines (123 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* file: constructor.js - provides construction prototype and __super__
* inheritance to JavaScript
* author: @dfkaye - david.kaye
* date: 2012-10-30
*
* To-DO (if ever)
* - better 'actual' support for extending natives (like Array) - could be
* bikeshedding, though...
*
* 11/20/12
* copied over to local
*
* 12/23/12
* renamed method .create to .extend
* made .extend require both args, not just one
* re-formatted defn to IIFE for pseudo-commonjs
*
* 3/3/13
* github repo opened ~ test factorings in progress
*
* 12/3/13
* change parent to __super__
* change exports support
*
* 3/27/14
* expose static __super__ and __super__.constructor properties
*/
;(function (exports) {
exports = (typeof module != 'undefined' && module.exports) || window;
exports.Constructor = Constructor;
/*
* @constructor function Constructor
*
* @param source - source must be either a function or an object specifier
* @return function - the new constructor function
*/
function Constructor(source) {
var sourceType = typeof(source);
var error = "Constructor(): invalid 'source' argument, must be a function or prototype, but was ";
var ctr;
if ('function' === sourceType) {
return source
}
if ('undefined' === sourceType) {
throw new ReferenceError(error + "undefined")
}
if ('object' !== sourceType || source === null) {
throw new TypeError(error + ('object' != sourceType ? sourceType + " [" + source + "]" : "null"))
}
ctr = source.constructor !== Object ? source.constructor : function () {};
ctr.prototype = source;
ctr.prototype.constructor = ctr;
return ctr
}
/*
* @method Constructor.extend
*
* @param source - required - source must be either a function or an object specifier
* @param target - required - target must be either a function or an object specifier
* @return function - the new constructor function
*/
Constructor.extend = extend;
function extend(source, target) {
var error = 'Constructor.extend(): ';
if (arguments.length < 2) {
throw new TypeError(error + 'requires 2 arguments, source and target.')
}
var sourceType = typeof(source);
var targetType = typeof(target);
/*
* pass-through if not functions; let Constructor throw errors if not objects either;
*/
var newSource = (sourceType !== 'function') ? new Constructor(source) : source;
var newConstructor = (targetType !== 'function') ? new Constructor(target) : target;
if (newSource == newConstructor) {
throw new ReferenceError(error + ' source and target arguments should not be identical')
}
var newPrototype;
function F() {}
// expose static __super_ and __super__.constructor properties
F.constructor = newSource;
newConstructor.__super__ = F;
// create our new prototype
F.prototype = newSource.prototype;
newPrototype = new F();
/*
* In order to support the target argument as an object specifier, we have
* to take the extra step of copying out its properties onto the new target
* function's prototype.
*/
if (targetType === 'object') {
var proto = newConstructor.prototype;
for (var k in proto) {
if (proto.hasOwnProperty(k)) {
newPrototype[k] = proto[k];
}
}
}
/*
* yes this makes 'constructor' an enumerable property
*/
newPrototype.constructor = newConstructor;
/*
* @method __super__ - a call-once method for initializing the super/parent constructor of
* this constructor. __super__ is replaced with an instance of the super/parent.
*/
newPrototype.__super__ = function () {
var __super__ = this.constructor.__super__;
var p = new __super__(this, arguments);
p.constructor.apply(p, arguments);
for (var k in p) {
if (p.hasOwnProperty(k)) {
//if (!(k in this)) {
this[k] = p[k];
}
}
this.__super__ = p;
};
newConstructor.prototype = newPrototype;
return newConstructor
}
}());