-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathProto.js
87 lines (79 loc) · 2.59 KB
/
Proto.js
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
////////// API //////////
// To be part of ECMAScript.next
if (!Object.getOwnPropertyDescriptors) {
Object.getOwnPropertyDescriptors = function (obj) {
var descs = {};
Object.getOwnPropertyNames(obj).forEach(function(propName) {
descs[propName] = Object.getOwnPropertyDescriptor(obj, propName);
});
return descs;
};
}
/**
* The root of all classes that adhere to "the prototypes as classes" protocol.
* The neat thing is that the class methods "new" and "extend" are automatically
* inherited by subclasses of this class (because Proto is in their prototype chain).
*/
var Proto = {
/**
* Class method: create a new instance and let instance method constructor() initialize it.
* "this" is the prototype of the new instance.
*/
new: function () {
var instance = Object.create(this);
if (instance.constructor) {
instance.constructor.apply(instance, arguments);
}
return instance;
},
/**
* Class method: subclass "this" (a prototype object used as a class)
*/
extend: function (subProps) {
// We cannot set the prototype of "subProps"
// => copy its contents to a new object that has the right prototype
var subProto = Object.create(this, Object.getOwnPropertyDescriptors(subProps));
subProto.super = this; // for super-calls
return subProto;
},
};
/**
* Optional: compatibility with constructor functions
*/
Function.prototype.extend = function(subProps) {
var constrFunc = this;
// Let a prototype-as-class extend a constructor function constrFunc.
// Step 1: tmpClass is Proto, but as a sub-prototype of constrFunc.prototype
var tmpClass = Proto.extend.call(constrFunc.prototype, Proto);
// Step 2: tmpClass is a prototype-as-class => use as such
return tmpClass.extend(subProps);
};
////////// Demo //////////
//***** Code *****
// Superclass
var Person = Proto.extend({
constructor: function (name) {
this.name = name;
},
describe: function() {
return "Person called "+this.name;
},
});
// Subclass
var Employee = Person.extend({
constructor: function (name, title) {
Employee.super.constructor.call(this, name);
this.title = title;
},
describe: function () {
return Employee.super.describe.call(this)+" ("+this.title+")";
},
});
//*/
/***** Interaction *****
var jane = Employee.new("Jane", "CTO"); // normally: new Employee(...)
> Employee.isPrototypeOf(jane) // normally: jane instanceof Employee
true
> jane.describe()
'Person called Jane (CTO)'
*/