1.
1 // Below is an example of how to use Object.create() to achieve classical inheritance. This is for single inheritance, which is all that JavaScript supports. 2 // Shape - superclass 3 function Shape() { 4 this.x = 0; 5 this.y = 0; 6 } 7 8 // superclass method 9 Shape.prototype.move = function(x, y) { 10 this.x += x; 11 this.y += y; 12 console.info('Shape moved.'); 13 }; 14 15 // Rectangle - subclass 16 function Rectangle() { 17 Shape.call(this); // call super constructor. 18 } 19 20 // subclass extends superclass 21 Rectangle.prototype = Object.create(Shape.prototype); 22 Rectangle.prototype.constructor = Rectangle; 23 24 var rect = new Rectangle(); 25 26 console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle);// true 27 console.log('Is rect an instance of Shape?', rect instanceof Shape);// true 28 rect.move(1, 1); // Outputs, 'Shape moved.' 29 30 // If you wish to inherit from multiple objects, then mixins are a possibility. 31 // The mixin function would copy the functions from the superclass prototype to the subclass prototype, the mixin function needs to be supplied by the user. An example of a mixin like function would be jQuery.extend(). 32 33 function MyClass() { 34 SuperClass.call(this); 35 OtherSuperClass.call(this); 36 } 37 38 MyClass.prototype = Object.create(SuperClass.prototype); // inherit 39 mixin(MyClass.prototype, OtherSuperClass.prototype); // mixin 40 41 MyClass.prototype.myMethod = function() { 42 // do a thing 43 }; 44 45 46 // Using propertiesObject argument with Object.create() 47 var o; 48 49 // create an object with null as prototype 50 o = Object.create(null); 51 52 53 o = {}; 54 // is equivalent to: 55 o = Object.create(Object.prototype); 56 57 58 // Example where we create an object with a couple of sample properties. 59 // (Note that the second parameter maps keys to *property descriptors*.) 60 o = Object.create(Object.prototype, { 61 // foo is a regular 'value property' 62 foo: { writable: true, configurable: true, value: 'hello' }, 63 // bar is a getter-and-setter (accessor) property 64 bar: { 65 configurable: false, 66 get: function() { return 10; }, 67 set: function(value) { console.log('Setting `o.bar` to', value); } 68 /* with ES5 Accessors our code can look like this 69 get function() { return 10; }, 70 set function(value) { console.log('setting `o.bar` to', value); } */ 71 } 72 }); 73 74 75 function Constructor() {} 76 o = new Constructor(); 77 // is equivalent to: 78 o = Object.create(Constructor.prototype); 79 // Of course, if there is actual initialization code in the 80 // Constructor function, the Object.create() cannot reflect it 81 82 83 // Create a new object whose prototype is a new, empty object 84 // and add a single property 'p', with value 42. 85 o = Object.create({}, { p: { value: 42 } }); 86 87 // by default properties ARE NOT writable, enumerable or configurable: 88 o.p = 24; 89 o.p; 90 // 42 91 92 o.q = 12; 93 for (var prop in o) { 94 console.log(prop); 95 } 96 // 'q' 97 98 delete o.p; 99 // false 100 101 // to specify an ES3 property 102 o2 = Object.create({}, { 103 p: { 104 value: 42, 105 writable: true, 106 enumerable: true, 107 configurable: true 108 } 109 }); 110 111 // Polyfill 112 // This polyfill covers the main use case which is creating a new object for which the prototype has been chosen but doesn't take the second argument into account. 113 114 // Note that while the setting of null as [[Prototype]] is supported in the real ES5 Object.create, this polyfill cannot support it due to a limitation inherent in versions of ECMAScript lower than 5. 115 if (typeof Object.create != 'function') { 116 Object.create = (function() { 117 var Temp = function() {}; 118 return function (prototype) { 119 if (arguments.length > 1) { 120 throw Error('Second argument not supported'); 121 } 122 if(prototype !== Object(prototype) && prototype !== null) { 123 throw TypeError('Argument must be an object or null'); 124 } 125 if (prototype === null) { 126 throw Error('null [[Prototype]] not supported'); 127 } 128 Temp.prototype = prototype; 129 var result = new Temp(); 130 Temp.prototype = null; 131 return result; 132 }; 133 })(); 134 }