| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | # object.js
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:52:26 +03:00
										 |  |  | _object.js_ provides a set of tools for making and maintaining object | 
					
						
							| 
									
										
										
										
											2020-04-25 01:14:00 +03:00
										 |  |  | constructors and for managing their inheritance relations. | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +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-04-26 21:49:03 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Installation
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | ```bash | 
					
						
							|  |  |  | $ 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
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Basic usage
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-04-25 02:00:40 +03:00
										 |  |  | `B.prototype` is _prototype_ of `A.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 | 
					
						
							|  |  |  | var B = object.Constructor('B', {__proto__: A.prototype}) | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | var C = object.Constructor('C', Object.create(B.prototype)) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```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-04-25 02:11:23 +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-04-15 00:42:20 +03:00
										 |  |  |     proto_attr: 'prototype attr value', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  |     get prop(){ | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  |         return 'propery value' }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  |     method: function(){ | 
					
						
							|  |  |  |         console.log('Base.method()') }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // initializer... | 
					
						
							|  |  |  |     __init__: function(){ | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  |         this.instance_attr = 'instance' | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  |     }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Item = object.Constructor('Item', { | 
					
						
							| 
									
										
										
										
											2019-07-17 00:29:52 +03:00
										 |  |  |     // inherit from Base... | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  |     __proto__: Base.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __init__: function(){ | 
					
						
							|  |  |  |         // call the "super" method... | 
					
						
							|  |  |  |         object.parent(this.__init__, this).call(this) | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 00:42:20 +03:00
										 |  |  |         this.item_attr = 'instance attribute value' | 
					
						
							| 
									
										
										
										
											2019-07-17 00:26:39 +03:00
										 |  |  |     }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-04-25 01:43:31 +03:00
										 |  |  |     // constructor as a function... | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  |     function(context, ...args){ | 
					
						
							|  |  |  |         // return the instance... | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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', { | 
					
						
							|  |  |  |     __call__: function(context, ...args){ | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-04-25 02:00:40 +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-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', { | 
					
						
							|  |  |  |     __new__: function(context, ...args){ | 
					
						
							|  |  |  |         return {} | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											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-04-25 02:00:40 +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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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>) | 
					
						
							|  |  |  |     -> <list> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Get parent method | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | parent(<method>, <this>) | 
					
						
							|  |  |  | parent(<method>, <name>, <this>) | 
					
						
							|  |  |  |     -> <parent-method> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 01:17:42 +03:00
										 |  |  | Get parent method and call it | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | parentCall(<method>, <this>) | 
					
						
							|  |  |  | parentCall(<method>, <name>, <this>) | 
					
						
							|  |  |  |     -> <result> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Mixin objects into a prototype chain | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | mixin(<root>, <object>, ...) | 
					
						
							|  |  |  |     -> <object> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Mixin contents of objects into one | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | mixinFlat(<root>, <object>, ...) | 
					
						
							|  |  |  |     -> <object> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | This is like `Object.assign(..)` but copies property objects rather than | 
					
						
							|  |  |  | property values. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 21:32:13 +03:00
										 |  |  | Make a raw (un-initialized) instance | 
					
						
							| 
									
										
										
										
											2020-04-26 19:30:49 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | makeRawInstance(<context>, <constructor>, ...) | 
					
						
							|  |  |  | 	-> <object> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-26 19:35:35 +03:00
										 |  |  | _EXPERIMENTAL: a shorthand to this is defined as `Constructor.__rawinstance__(..)`_ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | Define an object constructor | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | Constructor(<name>, <prototype>) | 
					
						
							|  |  |  | Constructor(<name>, <class-prototype>, <prototype>) | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  |     -> <constructor> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:52:00 +03:00
										 |  |  | Shorthand to `Constructor(..)` | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | C(<name>, ..) | 
					
						
							|  |  |  |     -> <constructor> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## 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. | 
					
						
							| 
									
										
										
										
											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 : --> |