├── Proto.js └── README /Proto.js: -------------------------------------------------------------------------------- 1 | ////////// API ////////// 2 | 3 | // To be part of ECMAScript.next 4 | if (!Object.getOwnPropertyDescriptors) { 5 | Object.getOwnPropertyDescriptors = function (obj) { 6 | var descs = {}; 7 | Object.getOwnPropertyNames(obj).forEach(function(propName) { 8 | descs[propName] = Object.getOwnPropertyDescriptor(obj, propName); 9 | }); 10 | return descs; 11 | }; 12 | } 13 | 14 | /** 15 | * The root of all classes that adhere to "the prototypes as classes" protocol. 16 | * The neat thing is that the class methods "new" and "extend" are automatically 17 | * inherited by subclasses of this class (because Proto is in their prototype chain). 18 | */ 19 | var Proto = { 20 | /** 21 | * Class method: create a new instance and let instance method constructor() initialize it. 22 | * "this" is the prototype of the new instance. 23 | */ 24 | new: function () { 25 | var instance = Object.create(this); 26 | if (instance.constructor) { 27 | instance.constructor.apply(instance, arguments); 28 | } 29 | return instance; 30 | }, 31 | 32 | /** 33 | * Class method: subclass "this" (a prototype object used as a class) 34 | */ 35 | extend: function (subProps) { 36 | // We cannot set the prototype of "subProps" 37 | // => copy its contents to a new object that has the right prototype 38 | var subProto = Object.create(this, Object.getOwnPropertyDescriptors(subProps)); 39 | subProto.super = this; // for super-calls 40 | return subProto; 41 | }, 42 | }; 43 | 44 | /** 45 | * Optional: compatibility with constructor functions 46 | */ 47 | Function.prototype.extend = function(subProps) { 48 | var constrFunc = this; 49 | // Let a prototype-as-class extend a constructor function constrFunc. 50 | // Step 1: tmpClass is Proto, but as a sub-prototype of constrFunc.prototype 51 | var tmpClass = Proto.extend.call(constrFunc.prototype, Proto); 52 | // Step 2: tmpClass is a prototype-as-class => use as such 53 | return tmpClass.extend(subProps); 54 | }; 55 | 56 | ////////// Demo ////////// 57 | 58 | //***** Code ***** 59 | // Superclass 60 | var Person = Proto.extend({ 61 | constructor: function (name) { 62 | this.name = name; 63 | }, 64 | describe: function() { 65 | return "Person called "+this.name; 66 | }, 67 | }); 68 | 69 | // Subclass 70 | var Employee = Person.extend({ 71 | constructor: function (name, title) { 72 | Employee.super.constructor.call(this, name); 73 | this.title = title; 74 | }, 75 | describe: function () { 76 | return Employee.super.describe.call(this)+" ("+this.title+")"; 77 | }, 78 | }); 79 | //*/ 80 | 81 | /***** Interaction ***** 82 | var jane = Employee.new("Jane", "CTO"); // normally: new Employee(...) 83 | > Employee.isPrototypeOf(jane) // normally: jane instanceof Employee 84 | true 85 | > jane.describe() 86 | 'Person called Jane (CTO)' 87 | */ 88 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Proto.js – prototypes as classes 2 | 3 | The core idea of Proto.js is that many things become simpler in JavaScript if you make the prototype the class and not the constructor. 4 | Details: http://www.2ality.com/2011/06/prototypes-as-classes.html 5 | 6 | Code: 7 | 8 | // Superclass 9 | var Person = Proto.extend({ 10 | constructor: function (name) { 11 | this.name = name; 12 | }, 13 | describe: function() { 14 | return "Person called "+this.name; 15 | } 16 | }); 17 | 18 | // Subclass 19 | var Employee = Person.extend({ 20 | constructor: function (name, title) { 21 | Employee.super.constructor.call(this, name); 22 | this.title = title; 23 | }, 24 | describe: function () { 25 | return Employee.super.describe.call(this)+" ("+this.title+")"; 26 | } 27 | }); 28 | 29 | Interaction: 30 | 31 | var jane = Employee.new("Jane", "CTO"); // normally: new Employee(...) 32 | 33 | > Employee.isPrototypeOf(jane) // normally: jane instanceof Employee 34 | true 35 | 36 | > jane.describe() 37 | 'Person called Jane (CTO)' 38 | --------------------------------------------------------------------------------