| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | # object.js
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | _object.js_ provides a meta-constructor and a set of tools and utilities  | 
					
						
							|  |  |  | to aid in object/instance construction and implementing dynamic data and  | 
					
						
							|  |  |  | functionality inheritance within the established JavaScript prototypical | 
					
						
							|  |  |  | object model and interfaces. | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:14:00 +03:00
										 |  |  | This is an alternative to the ES6 `class` syntax in JavaScript and provides  | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | several advantages:   | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - Simple way to define instance and "class" methods, properties and attributes, | 
					
						
							|  |  |  | - Uniform and minimalistic definition syntax based on basic JavaScript  | 
					
						
							|  |  |  |   object syntax, no special cases, special syntax or _"the same but slightly  | 
					
						
							|  |  |  |   different"_ ways to do things, | 
					
						
							|  |  |  | - _Transparently_ based on JavaScript's prototypical inheritance model, | 
					
						
							|  |  |  | - Granular instance construction (a-la _Python's_ `.__new__(..)`  | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  |   and `.__init__(..)` methods) | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - Simple way to define callable instances (including a-la _Python's_  | 
					
						
							|  |  |  |   `.__call__(..)`) | 
					
						
							|  |  |  | - Less restrictive: | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	- `new` is optional | 
					
						
							|  |  |  | 	- all input components are reusable | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | 	- no artificial restrictions | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Disadvantages compared to the `class` syntax:   | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - No _syntactic sugar_ | 
					
						
							|  |  |  | - Slightly more complicated calling of `parent` (_super_) methods | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | <table> | 
					
						
							|  |  |  | <tr valign="top"> | 
					
						
							|  |  |  | <td width="50%"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _object.js_ | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | var Base = object.Constructor('X', Array, { | 
					
						
							|  |  |  | 	constructor_attr: 'constructor', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	method: function(){ | 
					
						
							|  |  |  | 		return 'constructor' | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }, { | 
					
						
							|  |  |  | 	// prototype attribute... | 
					
						
							|  |  |  | 	attr: 'prototype', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get prop(){ | 
					
						
							|  |  |  | 		return 42 }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		this.instance_attr = 7 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td> | 
					
						
							|  |  |  | <td> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ES6_ | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | class X extends Array { | 
					
						
							|  |  |  | 	static constructor_attr = 'class' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static method(){ | 
					
						
							|  |  |  | 		return 'class' | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// instance attribute with default value... | 
					
						
							|  |  |  | 	attr = 'instance' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get prop(){ | 
					
						
							|  |  |  | 		return 42 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor(){ | 
					
						
							|  |  |  | 		super(...arguments)	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		this.instance_attr = 7 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </td> | 
					
						
							|  |  |  | </tr> | 
					
						
							|  |  |  | </table> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-04 01:16:48 +03:00
										 |  |  | ## Contents
 | 
					
						
							|  |  |  | - [object.js](#objectjs) | 
					
						
							|  |  |  | 	- [Contents](#contents) | 
					
						
							|  |  |  | 	- [Installation](#installation) | 
					
						
							|  |  |  | 	- [Basic usage](#basic-usage) | 
					
						
							|  |  |  | 		- [Inheritance](#inheritance) | 
					
						
							|  |  |  | 		- [Callable instances](#callable-instances) | 
					
						
							|  |  |  | 	- [Advanced usage](#advanced-usage) | 
					
						
							|  |  |  | 		- [Low level constructor](#low-level-constructor) | 
					
						
							|  |  |  | 		- [Extending the constructor](#extending-the-constructor) | 
					
						
							|  |  |  | 		- [Inheriting from native constructor objects](#inheriting-from-native-constructor-objects) | 
					
						
							|  |  |  | 		- [Extending native `.constructor(..)`](#extending-native-constructor) | 
					
						
							|  |  |  | 	- [Components](#components) | 
					
						
							|  |  |  | 	- [Utilities](#utilities) | 
					
						
							|  |  |  | 	- [Limitations](#limitations) | 
					
						
							|  |  |  | 		- [Can not mix unrelated native types](#can-not-mix-unrelated-native-types) | 
					
						
							|  |  |  | 	- [License](#license) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:49:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Installation
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | ```shell | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | $ npm install ig-object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:50:56 +03:00
										 |  |  | Or just download and drop [object.js](object.js) into your code. | 
					
						
							| 
									
										
										
										
											2020-04-26 21:49:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | ## Basic usage
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:49:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Include the code, this is compatible with both [node's](https://nodejs.org/) and | 
					
						
							|  |  |  | [RequireJS'](https://requirejs.org/) `require(..)` | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ```javascript | 
					
						
							|  |  |  | var object = require('ig-object') | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create a basic constructor... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | // NOTE: new is optional here... | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | var A = new object.Constructor('A') | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In _JavaScript_ constructor `B` inherits from constructor `A` iff  | 
					
						
							| 
									
										
										
										
											2020-05-02 03:02:10 +03:00
										 |  |  | `A.prototype` is _prototype_ of `B.prototype`. So to implement inheritance  | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | we simply need to _link_ the prototypes of two constructors via `.__proto__`, | 
					
						
							|  |  |  | `Object.create(..)` or other means. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var B = object.Constructor('B', { __extends__: A }) | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var C = object.Constructor('C', B, {}) | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | Now we can test this... | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ```javascript | 
					
						
							|  |  |  | var c = C() // or new C() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | c instanceof C // -> true | 
					
						
							|  |  |  | c instanceof B // -> true | 
					
						
							|  |  |  | c instanceof A // -> true | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Inheritance
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | //	  Base <--- Item | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | var Base = object.Constructor('Base', { | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	proto_attr: 'prototype attr value', | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	get prop(){ | 
					
						
							|  |  |  | 		return 'propery value' }, | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	method: function(){ | 
					
						
							|  |  |  | 		console.log('Base.method()') }, | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	// initializer... | 
					
						
							|  |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		this.instance_attr = 'instance' | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Item = object.Constructor('Item', { | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	// inherit from Base... | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 	__extends__: Base, | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		// call the "super" method... | 
					
						
							|  |  |  | 		object.parentCall(this.prototype.__init__, this) | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 		this.item_attr = 'instance attribute value' | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var SubItem = object.Constructor('SubItem', Item, { | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Callable instances
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | ```javascript | 
					
						
							|  |  |  | var Action = object.Constructor('Action', | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	// constructor as a function... | 
					
						
							|  |  |  | 	function(context, ...args){ | 
					
						
							|  |  |  | 		// return the instance... | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var action = new Action() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | // the instance now is a function... | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | action() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // a different way to do the above... | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | // | 
					
						
							|  |  |  | // This is the same as the above but a bit more convenient as we do  | 
					
						
							|  |  |  | // not need to use Object.assign(..) or object.mixinFlat(..) to define | 
					
						
							|  |  |  | // attributes and props. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | var Action2 = object.Constructor('Action2', { | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	__call__: function(context, ...args){ | 
					
						
							|  |  |  | 		return this | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:08:27 +03:00
										 |  |  | In the above cases both the _function constructor_ and the `.__call__(..)`  | 
					
						
							|  |  |  | method receive a `context` argument in addition to `this` context, those  | 
					
						
							|  |  |  | represent the two contexts relevant to the callable instance: | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | - Internal context (`this`)   | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  |   This always references the instance being called | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | - External context (`context`)	 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:03:42 +03:00
										 |  |  |   This is the object the instance is called from, i.e. the call _context_  | 
					
						
							|  |  |  |   (`window` or `global` by default) | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | If the prototype is explicitly defined as a function then it is the  | 
					
						
							| 
									
										
										
										
											2020-04-25 02:05:54 +03:00
										 |  |  | user's responsibility to call `.__call__(..)` method. | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | **Notes:** | 
					
						
							|  |  |  | - the two approaches (_function_ vs. `.__call__(..)`) will produce  | 
					
						
							|  |  |  |   slightly different results, the difference is in `.prototype`, in the | 
					
						
							|  |  |  |   first case it is a _function_ while in the second an object with a  | 
					
						
							|  |  |  |   `.__call__(..)` method.   | 
					
						
							|  |  |  |   (this may change in the future) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 21:48:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Advanced usage
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | ### Low level constructor
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | ```javascript | 
					
						
							|  |  |  | var LowLevel = object.Constructor('LowLevel', { | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	__new__: function(context, ...args){ | 
					
						
							|  |  |  | 		return {} | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:08:27 +03:00
										 |  |  | Like _function constructor_ and `.__call__(..)` this also has two contexts, | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | but the internal context is different -- as it is the job of `.__new__(..)` | 
					
						
							| 
									
										
										
										
											2020-04-25 02:08:27 +03:00
										 |  |  | to create an instance, at time of call the instance does not exist and `this` | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | references the `.prototype` object. | 
					
						
							|  |  |  | The external context is the same as above. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Contexts: | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | - Internal context (`this`)   | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  |   References the `.prototype` of the constructor. | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | - External context (`context`)	 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:03:42 +03:00
										 |  |  |   This is the object the instance is called from, i.e. the call _context_  | 
					
						
							|  |  |  |   (`window` or `global` by default), the same as for function constructor  | 
					
						
							|  |  |  |   and `.__call__(..)`. | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  |   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The value `.__new__(..)`returns is used as the instance and gets linked  | 
					
						
							|  |  |  | in the prototype chain. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This has priority over the callable protocols above, thus the user must | 
					
						
							| 
									
										
										
										
											2020-04-25 02:08:27 +03:00
										 |  |  | take care of both the _function constructor_ and `prototype.__call__(..)`  | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | handling. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 19:35:35 +03:00
										 |  |  | **Notes:**  | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - `.__new__(..)` is an instance method, contrary to _Python_ (the  | 
					
						
							|  |  |  |   inspiration for this protocol). This is done intentionally as in | 
					
						
							| 
									
										
										
										
											2020-04-26 21:32:13 +03:00
										 |  |  |   JavaScript there is no distinction between an instance and a class and | 
					
						
							|  |  |  |   defining `.__new__(..)` in the class would both add complexity as well  | 
					
						
							|  |  |  |   as restrict the use-cases for the constructor. | 
					
						
							| 
									
										
										
										
											2020-04-26 19:35:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | ### Extending the constructor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var C = object.Constructor('C', | 
					
						
							|  |  |  | 	// this will get mixed into the constructor C... | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		constructor_attr: 123, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 		constructorMethod: function(){ | 
					
						
							|  |  |  | 			// ... | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ... | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 		instanceMethod: function(){ | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 			// get constructor data... | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 			var x = this.constructor.constructor_attr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// ... | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		// ... | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | And the same thing while extending... | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var D = object.Constructor('D', | 
					
						
							|  |  |  | 	// this will get mixed into C(..)... | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 		__extends__: C, | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// ... | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 		// ... | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | Note that `.__extends__` can be written in either block, this is done  | 
					
						
							|  |  |  | for convenience and to keep it as close as possible to the definition top. | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 22:19:55 +03:00
										 |  |  | ### Inheriting from native constructor objects
 | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var myArray = object.Constructor('myArray', { | 
					
						
							|  |  |  | 	__extends__: Array, | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 22:19:55 +03:00
										 |  |  | All special methods and protocols defined by _object.js_ except for  | 
					
						
							|  |  |  | `.__new__(..)` will work here without change. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For details on `.__new__(..)` and native `.constructor(..)` interaction  | 
					
						
							|  |  |  | see: [Extending native `.constructor(..)`](#extending-native-constructor) | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Extending native `.constructor(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Extending `.constructor(..)` is not necessary in most cases as  | 
					
						
							|  |  |  | `.__init__(..)` will do everything generally needed, except for instance  | 
					
						
							|  |  |  | replacement. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | var myArray = object.Constructor('myArray', { | 
					
						
							|  |  |  | 	__extends__: Array, | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	__new__: function(context, ...args){ | 
					
						
							|  |  |  | 		var obj = Reflect.construct(myArray.__proto__, args, myArray) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return obj | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ## Components
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Get sources for attribute | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | sources(<object>, <name>) | 
					
						
							|  |  |  | sources(<object>, <name>, <callback>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <list> | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 02:01:00 +03:00
										 |  |  | Get parent attribute value or method | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-04-30 02:01:00 +03:00
										 |  |  | parent(<prototype>, <name>) | 
					
						
							|  |  |  | 	-> <parent-value> | 
					
						
							| 
									
										
										
										
											2020-04-27 04:16:35 +03:00
										 |  |  | 	-> undefined | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 02:01:00 +03:00
										 |  |  | parent(<method>, <this>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <parent-method> | 
					
						
							| 
									
										
										
										
											2020-04-27 04:16:35 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 02:28:08 +03:00
										 |  |  | _Edge case: The `parent(<method>, ..)` has one potential pitfall -- in  | 
					
						
							|  |  |  | the rare case where a prototype chain contains two or more references  | 
					
						
							|  |  |  | to the same method under the same name, `parent(..)` can't distinguish  | 
					
						
							| 
									
										
										
										
											2020-04-30 02:29:15 +03:00
										 |  |  | between these references and will always return the second one._ | 
					
						
							| 
									
										
										
										
											2020-04-30 02:20:29 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | Get parent property descriptor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | parentProperty(<prototype>, <name>) | 
					
						
							|  |  |  | 	-> <prop-descriptor> | 
					
						
							|  |  |  | 	-> undefined | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 01:17:42 +03:00
										 |  |  | Get parent method and call it | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-04-27 04:16:35 +03:00
										 |  |  | parentCall(<prototype>, <name>, <this>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <result> | 
					
						
							| 
									
										
										
										
											2020-04-30 02:20:29 +03:00
										 |  |  | 	-> undefined | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 02:10:01 +03:00
										 |  |  | parentCall(<method>, <this>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <result> | 
					
						
							| 
									
										
										
										
											2020-04-27 04:16:35 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2020-04-27 01:17:42 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Mixin objects into a prototype chain | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-02 00:46:51 +03:00
										 |  |  | mixin(<root>, <object>, ..) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <object> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Mixin contents of objects into one | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-02 00:46:51 +03:00
										 |  |  | mixinFlat(<root>, <object>, ..) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <object> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | This is like `Object.assign(..)` but copies property objects rather than | 
					
						
							|  |  |  | property values. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:32:13 +03:00
										 |  |  | Make a raw (un-initialized) instance | 
					
						
							| 
									
										
										
										
											2020-04-26 19:30:49 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-02 00:46:51 +03:00
										 |  |  | makeRawInstance(<context>, <constructor>, ..) | 
					
						
							| 
									
										
										
										
											2020-04-26 19:30:49 +03:00
										 |  |  | 	-> <object> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:46:51 +03:00
										 |  |  | A shorthand to this is `Constructor.__rawinstance__(context, ..)`. | 
					
						
							| 
									
										
										
										
											2020-04-26 19:35:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Define an object constructor | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-02 19:55:05 +03:00
										 |  |  | Constructor(<name>) | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | Constructor(<name>, <prototype>) | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | Constructor(<name>, <parent-constructor>, <prototype>) | 
					
						
							|  |  |  | Constructor(<name>, <constructor-mixin>, <prototype>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <constructor> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:52:00 +03:00
										 |  |  | Shorthand to `Constructor(..)` | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | C(<name>, ..) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <constructor> | 
					
						
							| 
									
										
										
										
											2020-04-25 01:52:00 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Utilities
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Align text to shortest leading whitespace | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | normalizeIndent(<text>) | 
					
						
							|  |  |  | normalizeIndent(<text>, <tab-size>) | 
					
						
							|  |  |  | 	-> <text> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is used to format `.toString(..)` return values for nested functions | 
					
						
							|  |  |  | to make source printing in console more pleasant to read. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | ## Limitations
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-04 01:16:48 +03:00
										 |  |  | ### Can not mix unrelated native types
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | At this point we can't mix native types, for example it is not possible  | 
					
						
							|  |  |  | to make a callable `Array` object... | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 15:18:41 +03:00
										 |  |  | This is not possible in current _JavaScript_ implementations directly  | 
					
						
							|  |  |  | as most builtin objects rely on "hidden" mechanics and there is no way  | 
					
						
							|  |  |  | to combine or inherit them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To illustrate: | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 15:18:41 +03:00
										 |  |  | // produces an Array that looks like a function but does not act like one... | 
					
						
							|  |  |  | var a = Reflect.construct(Array, [], Function) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // creates a function that looks like an array...  | 
					
						
							|  |  |  | var b = Reflect.construct(Function, [], Array) | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 15:18:41 +03:00
										 |  |  | So these will produce partially broken instances: | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-03 15:18:41 +03:00
										 |  |  | var A = object.Constructor('A', Array, function(){ .. }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var B = object.Constructor('B', Array, { | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 	__call__: function(){ .. }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 15:18:41 +03:00
										 |  |  | Essentially this issue and the inability to implement it without  | 
					
						
							|  |  |  | emulation, shows the side-effects of two "features" in _JavaScript_: | 
					
						
							|  |  |  | - lack of multiple inheritance | 
					
						
							|  |  |  | - _hidden_ protocols/functionality (namely: calls, attribute access) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Still, this is worth some thought. | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## License
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [BSD 3-Clause License](./LICENSE) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  | Copyright (c) 2019, Alex A. Naanou,   | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:14:00 +03:00
										 |  |  | <!-- vim:set ts=4 sw=4 spell : --> |