| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | # object.js
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | object.js provides a set of tools for constructing 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:   | 
					
						
							|  |  |  | - simple way to define normal and class methods, properties and attributes, | 
					
						
							|  |  |  | - uniform and minimalistic definition syntax based on basic JavaScript  | 
					
						
							|  |  |  |   object syntax no special cases or special syntax, | 
					
						
							| 
									
										
										
										
											2020-04-25 01:14:00 +03:00
										 |  |  | - _transparently_ based on _JavaScript's_ prototypical inheritance model, | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | - more granular instance construction (a-la _Python's_ `.__new__(..)`  | 
					
						
							|  |  |  |   and `.__init__(..)` methods) | 
					
						
							|  |  |  | - less restrictive: | 
					
						
							|  |  |  |     - `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-25 01:14:00 +03:00
										 |  |  | - no _syntactic sugar_ | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | - slightly more complicated calling of _super_ or `parent` methods | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 02:00:40 +03:00
										 |  |  | ## Basic usage
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | // | 
					
						
							|  |  |  | //    Base | 
					
						
							|  |  |  | //     ^ | 
					
						
							|  |  |  | //     | | 
					
						
							|  |  |  | //    Item | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 : --> |