| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | # object.js
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 03:39:21 +03:00
										 |  |  | _object.js_ is a set of tools and abstractions to create and manage  | 
					
						
							|  |  |  | constructors, objects and prototype chains in idiomatic JavaScript. | 
					
						
							| 
									
										
										
										
											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-05-07 03:40:23 +03:00
										 |  |  | - _Uniform and minimalistic_ definition "syntax" based on basic JavaScript  | 
					
						
							| 
									
										
										
										
											2020-05-07 03:39:21 +03:00
										 |  |  |   object literals. No special cases, special syntax or _"the same but slightly | 
					
						
							| 
									
										
										
										
											2020-05-08 16:00:00 +03:00
										 |  |  |   different"_ ways to do things, trying to adhere to  | 
					
						
							|  |  |  |   [POLS](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) | 
					
						
							|  |  |  |   as much as possible, | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - _Transparently_ based on JavaScript's prototypical inheritance model, | 
					
						
							| 
									
										
										
										
											2020-05-07 03:39:21 +03:00
										 |  |  | - Produces fully introspectable constructors/instances, | 
					
						
							| 
									
										
										
										
											2020-05-07 03:41:05 +03:00
										 |  |  | - Does not try to emulate constructs foreign to JavaScript (i.e. classes), | 
					
						
							| 
									
										
										
										
											2020-05-06 19:00:39 +03:00
										 |  |  | - Granular 2-stage instance construction and initialization (a-la  | 
					
						
							|  |  |  |   _Python's_ `.__new__(..)` and `.__init__(..)` methods), | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - Simple way to define callable instances (including a-la _Python's_  | 
					
						
							| 
									
										
										
										
											2020-05-06 13:45:54 +03:00
										 |  |  |   `.__call__(..)`), | 
					
						
							| 
									
										
										
										
											2020-04-26 21:43:00 +03:00
										 |  |  | - Less restrictive: | 
					
						
							| 
									
										
										
										
											2020-05-06 13:45:54 +03:00
										 |  |  | 	- `new` is optional, | 
					
						
							| 
									
										
										
										
											2020-05-06 19:00:39 +03:00
										 |  |  | 	- all input components are reusable JavaScript objects, | 
					
						
							| 
									
										
										
										
											2020-05-06 13:45:54 +03:00
										 |  |  | 	- no artificial restrictions. | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Disadvantages compared to the `class` syntax:   | 
					
						
							| 
									
										
										
										
											2020-05-06 13:45:54 +03:00
										 |  |  | - No _syntactic sugar_, | 
					
						
							|  |  |  | - Slightly more complicated calling of `parent` (_super_) methods. | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 13:45:54 +03:00
										 |  |  | Note that the produced constructors and objects are functionally  | 
					
						
							|  |  |  | identical (almost) to the ones produced via ES6 classes and are  | 
					
						
							|  |  |  | interchangeable with them. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 03:15:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Here is a basic comparison: | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | <table border="0" width="100%"> | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | <tr valign="top"> | 
					
						
							| 
									
										
										
										
											2020-05-06 03:15:39 +03:00
										 |  |  | <td width="50%"> | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | _object.js_ | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-06 13:11:54 +03:00
										 |  |  | var A = object.Constructor('A', { | 
					
						
							|  |  |  | 	// prototype attribute (inherited)... | 
					
						
							|  |  |  | 	attr: 'prototype', | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	method: function(){ | 
					
						
							| 
									
										
										
										
											2020-05-06 13:11:54 +03:00
										 |  |  | 		// ... | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var B = object.Constructor('B', A, { | 
					
						
							|  |  |  | 	constructor_attr: 'constructor', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor_method: function(){ | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 		return 'constructor' | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }, { | 
					
						
							|  |  |  | 	get prop(){ | 
					
						
							|  |  |  | 		return 42 }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		this.instance_attr = 7 | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 13:56:14 +03:00
										 |  |  | - No _direct_ way to do "private" definitions, | 
					
						
							|  |  |  | - Clear separation of constructor and `.prototype`   | 
					
						
							|  |  |  |   For example, in `B`: | 
					
						
							| 
									
										
										
										
											2020-05-06 13:11:54 +03:00
										 |  |  | 	- First block (optional) is merged with `B`, | 
					
						
							|  |  |  | 	- Second block _is_ the `B.prototype`, | 
					
						
							| 
									
										
										
										
											2020-05-07 03:29:23 +03:00
										 |  |  | - No special syntax, stands out less. | 
					
						
							| 
									
										
										
										
											2020-05-06 03:15:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | </td> | 
					
						
							| 
									
										
										
										
											2020-05-06 03:15:39 +03:00
										 |  |  | <td> | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | _ES6_ | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-06 13:11:54 +03:00
										 |  |  | class A { | 
					
						
							|  |  |  | 	// instance attribute (copied)... | 
					
						
							|  |  |  | 	attr = 'instance' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	method(){ | 
					
						
							|  |  |  | 		// ... | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class B extends A { | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 	static constructor_attr = 'class' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 13:11:54 +03:00
										 |  |  | 	static constructor_method(){ | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 		return 'class' | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	get prop(){ | 
					
						
							|  |  |  | 		return 42 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor(){ | 
					
						
							|  |  |  | 		super(...arguments)	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		this.instance_attr = 7 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 13:18:36 +03:00
										 |  |  | - Syntax pretty but _misleading_;   | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  |   calling a _constructor_ a class is not correct, | 
					
						
							|  |  |  | - `static` and instance definitions are not separated, | 
					
						
							|  |  |  | - lots of details done non-transparently under the hood. | 
					
						
							| 
									
										
										
										
											2020-05-06 02:37:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | </td> | 
					
						
							|  |  |  | </tr> | 
					
						
							|  |  |  | </table> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 03:15:39 +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) | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | 		- [Mix-ins](#mix-ins) | 
					
						
							| 
									
										
										
										
											2020-05-06 05:44:05 +03:00
										 |  |  | 	- [Advanced usage](#advanced-usage) | 
					
						
							| 
									
										
										
										
											2020-05-04 01:16:48 +03:00
										 |  |  | 		- [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) | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 		- [`STOP`](#stop) | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 		- [`sources(..)`](#sources) | 
					
						
							| 
									
										
										
										
											2020-05-23 17:02:37 +03:00
										 |  |  | 		- [`values(..)`](#values) | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 		- [`parent(..)`](#parent) | 
					
						
							|  |  |  | 		- [`parentProperty(..)`](#parentproperty) | 
					
						
							|  |  |  | 		- [`parentCall(..)`](#parentcall) | 
					
						
							|  |  |  | 		- [`mixin(..)`](#mixin) | 
					
						
							| 
									
										
										
										
											2020-05-07 21:20:20 +03:00
										 |  |  | 		- [`mixins(..)`](#mixins) | 
					
						
							|  |  |  | 		- [`hasMixin(..)`](#hasmixin) | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 		- [`mixout(..)`](#mixout) | 
					
						
							|  |  |  | 		- [`mixinFlat(..)`](#mixinflat) | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | 		- [`RawInstance(..)`](#rawinstance) | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 		- [`Constructor(..)` / `C(..)`](#constructor--c) | 
					
						
							| 
									
										
										
										
											2020-05-04 01:16:48 +03:00
										 |  |  | 	- [Utilities](#utilities) | 
					
						
							| 
									
										
										
										
											2020-05-08 16:32:54 +03:00
										 |  |  | 		- [`normalizeIndent(..)` / `normalizeTextIndent(..)`](#normalizeindent--normalizetextindent) | 
					
						
							| 
									
										
										
										
											2020-05-07 21:20:20 +03:00
										 |  |  | 		- [`match(..)`](#match) | 
					
						
							| 
									
										
										
										
											2020-05-04 01:16:48 +03:00
										 |  |  | 	- [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-05-08 18:29:22 +03:00
										 |  |  | var A = new object.Constructor('A', {}) | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 03:39:32 +03:00
										 |  |  | var B = object.Constructor('B', 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-05-08 18:29:22 +03:00
										 |  |  | **Note:** | 
					
						
							|  |  |  | - in `object.Constructor('X', A)` the second argument is used as the  | 
					
						
							|  |  |  |   _prototype_, to use `A` as a parent constructor add an empty object  | 
					
						
							|  |  |  |   as a third argument, i.e. 'object.Constructor('X', A, {})'   | 
					
						
							|  |  |  |   (see: [`Constructor(..)` / `C(..)`](#constructor--c) for more info) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06 21:48:38 +03:00
										 |  |  | //	  Base <--- Item <--- SubItem | 
					
						
							| 
									
										
										
										
											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
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 03:39:32 +03:00
										 |  |  | var Item = object.Constructor('Item', Base, { | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | 	method: function(){ | 
					
						
							|  |  |  | 		// ...  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// call the "super" method... | 
					
						
							|  |  |  | 		return object.parentCall(Item.prototype, 'method', this, ...arguments) | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		// call the "super" method... | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | 		object.parentCall(this.__init__, this, ...arguments) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 14:42:21 +03:00
										 |  |  | // a more flexible approach... | 
					
						
							| 
									
										
										
										
											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){ | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | 		// call the callable parent... | 
					
						
							|  |  |  | 		return object.parentCall(Action2.prototype, '__call__', this, ...arguments) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2020-04-10 18:30:55 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 14:42:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var action = Action() | 
					
						
							|  |  |  | var action2 = new Action2() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // the instances are now functions... | 
					
						
							|  |  |  | action() | 
					
						
							|  |  |  | action2() | 
					
						
							| 
									
										
										
										
											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-24 23:59:01 +03:00
										 |  |  | When calling the parent passing `'__call__'` will get the parent in both  | 
					
						
							|  |  |  | the function and `.__call__(..)` implementations, but extra care must be  | 
					
						
							|  |  |  | taken in passing the reference prototype to `.parentCall(..)`, the instance | 
					
						
							|  |  |  | is implemented as a proxy function that will pass the arguments to the  | 
					
						
							|  |  |  | implementation (i.e. `this.constructor.prototype(..)`) so this proxy  | 
					
						
							|  |  |  | function as well as the `.constructor.prototype(..)` are valid implementations | 
					
						
							|  |  |  | and both will be retrieved by `sources(this, '__call__')`,  | 
					
						
							|  |  |  | `values(this, '__call__')` and by extension `parent(this, '__call__')`  | 
					
						
							|  |  |  | and friends, so this is another reason not to use `this` in the general  | 
					
						
							|  |  |  | case. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | **Notes:** | 
					
						
							| 
									
										
										
										
											2020-05-25 00:53:56 +03:00
										 |  |  | - The two approaches (_function_ vs. `.__call__(..)`) will produce  | 
					
						
							| 
									
										
										
										
											2020-05-08 14:42:21 +03:00
										 |  |  |   functionally identical but structurally different constructors/objects,  | 
					
						
							| 
									
										
										
										
											2020-05-08 15:42:32 +03:00
										 |  |  |   the difference is in `.prototype` -- what is defined as the prototype | 
					
						
							| 
									
										
										
										
											2020-05-08 16:00:00 +03:00
										 |  |  |   _is_ the prototype (_POLS_), so we get: | 
					
						
							| 
									
										
										
										
											2020-05-08 14:42:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 16:00:00 +03:00
										 |  |  |   	- _prototype function_ -> `.prototype` is that exact function object, | 
					
						
							|  |  |  | 	- `.__call__(..)` -> `.prototype` is _the_ object with the `.__call__(..)`  | 
					
						
							|  |  |  | 	  method. | 
					
						
							| 
									
										
										
										
											2020-05-08 14:42:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   The instance in both cases is a function wrapper that will proxy the  | 
					
						
							|  |  |  |   call to the corresponding implementation. | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  |   (this may change in the future) | 
					
						
							| 
									
										
										
										
											2020-05-25 00:53:56 +03:00
										 |  |  | - Making an object callable does not guarantee that `<obj> instanceof Function` | 
					
						
							|  |  |  |   will be `true`, though `typeof(<obj>) == 'function'`will always work. | 
					
						
							|  |  |  |   To satisfy the `instanceof Function` test the prototype tree must be  | 
					
						
							|  |  |  |   rooted in `Function`. | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | ### Mix-ins
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Prototype-based mixin... | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | var utilityMixin = { | 
					
						
							|  |  |  | 	utility: function(){ | 
					
						
							|  |  |  | 		// ... | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Base = object.Constructor('Base')  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:35:48 +03:00
										 |  |  | // normal instance prototype chain: | 
					
						
							|  |  |  | //	b -> Base.prototype -> ..  | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | var b = Base() | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // mixin directly into the instance... | 
					
						
							| 
									
										
										
										
											2020-05-07 21:35:48 +03:00
										 |  |  | // | 
					
						
							|  |  |  | // now the prototype chain looks like this: | 
					
						
							|  |  |  | //	b -> mixinFlat({}, utilityMixin) -> Base.prototype -> .. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | object.mixin(b, utilityMixin) | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `.mixin(..)` will copy the contents of `utilityMixin` into the prototype  | 
					
						
							| 
									
										
										
										
											2020-05-07 21:35:48 +03:00
										 |  |  | chain between `b` and `b.__proto__`. | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 05:37:28 +03:00
										 |  |  | We can also remove the mixin... | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-07 21:35:48 +03:00
										 |  |  | o.mixout(b, utilityMixin) | 
					
						
							| 
									
										
										
										
											2020-05-06 05:37:28 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:35:48 +03:00
										 |  |  | The mixed-in data is removed iff a [matching](#match) object is found in  | 
					
						
							|  |  |  | the chain with the same attributes as `utilityMixin` and with each  | 
					
						
							|  |  |  | attribute matching identity with the corresponding attribute in the mixin. | 
					
						
							| 
									
										
										
										
											2020-05-06 05:37:28 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 05:30:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Constructor-based mixin... | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | var UtilityMixin = function(parent){ | 
					
						
							|  |  |  | 	return object.Constructor(parent.name + '+utils', parent, utilityMixin) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Mixed = object.Constructor('Mixed', UtilityMixin(Base), { | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var m = Mixed() | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-06 21:56:24 +03:00
										 |  |  | Like [_function constructor_ and `.__call__(..)`](#callable-instances)  | 
					
						
							|  |  |  | this also has two contexts, but the internal context is different -- as | 
					
						
							|  |  |  | it is the job of `.__new__(..)` to create an instance, at time of call  | 
					
						
							|  |  |  | the instance does not exist and `this` references the `.prototype`  | 
					
						
							|  |  |  | object. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 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-05-02 22:09:37 +03:00
										 |  |  | ### Extending the constructor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-08 04:17:03 +03:00
										 |  |  | var C = object.Constructor('C', { | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | 	// this will get mixed into the constructor C... | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:17:03 +03:00
										 |  |  | 	constructor_attr: 123, | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:17:03 +03:00
										 |  |  | 	constructorMethod: function(){ | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 		// ... | 
					
						
							| 
									
										
										
										
											2020-05-08 04:17:03 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }, { | 
					
						
							|  |  |  | 	instanceMethod: function(){ | 
					
						
							|  |  |  | 		// get constructor data... | 
					
						
							|  |  |  | 		var x = this.constructor.constructor_attr | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// ... | 
					
						
							| 
									
										
										
										
											2020-05-08 04:17:03 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2020-05-02 22:09:37 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06 19:34:10 +03:00
										 |  |  | var D = object.Constructor('D', C, { | 
					
						
							| 
									
										
										
										
											2020-05-08 04:16:13 +03:00
										 |  |  | 	// ... | 
					
						
							|  |  |  | }, { | 
					
						
							|  |  |  | 	// ... | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											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-06 03:39:32 +03:00
										 |  |  | var myArray = object.Constructor('myArray', 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-06 03:39:32 +03:00
										 |  |  | var myArray = object.Constructor('myArray', 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-05-06 14:59:55 +03:00
										 |  |  | Note that all of the following are generic and will work on any relevant | 
					
						
							|  |  |  | JavaScript object. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:53:31 +03:00
										 |  |  | For example, this will happily create a normal native array object  | 
					
						
							|  |  |  | `['a', 'b', 'c']`: | 
					
						
							| 
									
										
										
										
											2020-05-06 14:59:55 +03:00
										 |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | var l = object.RawInstance(null, Array, 'a', 'b', 'c') | 
					
						
							| 
									
										
										
										
											2020-05-06 14:59:55 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### `STOP`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Used in [`sources(..)`](#sources), [`values(..)`](#values) and  | 
					
						
							|  |  |  | [`mixins(..)`](#mixins) to stop the search before it reaches the top of  | 
					
						
							|  |  |  | the prototype chain. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `sources(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-07 21:02:05 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | callback(<source>) | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> STOP  | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> <value> | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | The `callback(..)` controls the output of `sources(..)` by returning  | 
					
						
							|  |  |  | one of the following: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - `object.STOP`   | 
					
						
							| 
									
										
										
										
											2020-05-24 00:49:51 +03:00
										 |  |  |   This will make `sources(..)` stop and return the `<list>` up to and  | 
					
						
							|  |  |  |   including the object that triggered the _stop_. | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | - `undefined`   | 
					
						
							| 
									
										
										
										
											2020-05-24 00:49:51 +03:00
										 |  |  |   Add the object triggering `callback(..)` in `<list>` as-is and continue.  | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | - array   | 
					
						
							| 
									
										
										
										
											2020-05-24 00:49:51 +03:00
										 |  |  |   The containing values will be merged into the result list and continue. | 
					
						
							|  |  |  |   This is a way to either skip an object by returning `[]` or multiple  | 
					
						
							|  |  |  |   values instead of one. | 
					
						
							| 
									
										
										
										
											2020-05-24 00:46:32 +03:00
										 |  |  | - `<value>`   | 
					
						
							| 
									
										
										
										
											2020-05-24 00:49:51 +03:00
										 |  |  |   Add to the resulting `<list>` as-is instead of the object triggering  | 
					
						
							|  |  |  |   `callback(..)` and continue. | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | Special case: get callable implementations | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | sources(<object>, '__call__') | 
					
						
							|  |  |  | sources(<object>, '__call__', <callback>) | 
					
						
							|  |  |  | 	-> <list> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This will get the callable implementations regardless of the actual | 
					
						
							|  |  |  | implementation details, i.e. both function prototype or `.__call__(..)`  | 
					
						
							|  |  |  | methods will be matched. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | ### `values(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Get values for attribute in prototype chain | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | values(<object>, <name>) | 
					
						
							|  |  |  | values(<object>, <name>, <callback>) | 
					
						
							|  |  |  | 	-> <list> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | callback(<value>, <source>) | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> STOP  | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> <value> | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Get property descriptors for attribute in prototype chain | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | values(<object>, <name>, true) | 
					
						
							|  |  |  | values(<object>, <name>, <callback>, true) | 
					
						
							|  |  |  | 	-> <list> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | callback(<descriptor>, <source>) | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> STOP  | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> <value> | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | See [`sources(..)`](#sources) for docs on `callback(..)` and special cases. | 
					
						
							| 
									
										
										
										
											2020-05-23 16:56:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `parent(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-24 23:59:01 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It is recommended to use the relative`<constructor>.prototype` as  | 
					
						
							|  |  |  | `<prototype>` and in turn not recommended to use `this` or `this.__proto__`  | 
					
						
							|  |  |  | as they will not provide the appropriate reference point in the prototype  | 
					
						
							|  |  |  | chain for the current method and may result in infinite recursion. | 
					
						
							| 
									
										
										
										
											2020-04-27 04:16:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 23:59:01 +03:00
										 |  |  | For access to parent methods the following special case is better. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											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-05-24 23:59:01 +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-05-24 23:59:01 +03:00
										 |  |  | Special case: get the parent callable implementation | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | parent(<prototype>, '__call__') | 
					
						
							|  |  |  | 	-> <parent-value> | 
					
						
							|  |  |  | 	-> undefined | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | See [`sources(..)`](#sources) for more info on the special case. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### `parentProperty(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | Get parent property descriptor | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | parentProperty(<prototype>, <name>) | 
					
						
							|  |  |  | 	-> <prop-descriptor> | 
					
						
							|  |  |  | 	-> undefined | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `parentCall(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-24 23:59:01 +03:00
										 |  |  | Special case: call the parent callable implementation | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | parentCall(<prototype>, '__call__', <this>) | 
					
						
							|  |  |  | 	-> <result> | 
					
						
							|  |  |  | 	-> undefined | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | See [`parent(..)`](#parent) and [`sources(..)`](#sources) for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 01:17:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `mixin(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | _Mixin_ objects into a prototype chain | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | mixin(<base>, <object>, ..) | 
					
						
							|  |  |  | 	-> <base> | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | This will link the base `.__proto__` to the last _mixin_ in chain,  | 
					
						
							|  |  |  | keeping the prototype visibility the same. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This will copy the content of each input object without touching the  | 
					
						
							|  |  |  | objects themselves, making them fully reusable. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | ### `mixins(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Get matching mixins | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | mixins(<base>, <object>) | 
					
						
							|  |  |  | mixins(<base>, [<object>, ..]) | 
					
						
							|  |  |  | mixins(<base>, <object>, <callback>) | 
					
						
							|  |  |  | mixins(<base>, [<object>, ..], <callback>) | 
					
						
							|  |  |  | 	-> list | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | callback(<match>, <object>, <parent>) | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> STOP  | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | 	-> undefined | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | 	-> <value> | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-24 00:37:52 +03:00
										 |  |  | See [`sources(..)`](#sources) for docs on `callback(..)` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### `hasMixin(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:24:09 +03:00
										 |  |  | Check if _base_ object has _mixin_ | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | hasMixin(<base>, <mixin>) | 
					
						
							|  |  |  | 	-> <bool> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `mixout(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:24:09 +03:00
										 |  |  | Remove the _first_ match matching input _mixin_ from _base_  | 
					
						
							| 
									
										
										
										
											2020-05-08 04:19:48 +03:00
										 |  |  | of _base_ | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | mixout(<base>, <object>, ..) | 
					
						
							| 
									
										
										
										
											2020-05-06 19:27:34 +03:00
										 |  |  | mixout(<base>, 'first', <object>, ..) | 
					
						
							|  |  |  | 	-> <base> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:24:09 +03:00
										 |  |  | Remove _all_ occurrences of each matching input _mixin_ from _base_ | 
					
						
							| 
									
										
										
										
											2020-05-06 19:27:34 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | mixout(<base>, 'all', <object>, ..) | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 	-> <base> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | This is the opposite of `mixin(..)` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +03:00
										 |  |  | ### `mixinFlat(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 19:34:10 +03:00
										 |  |  | Mixin contents of objects into one _base_ object | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 19:00:39 +03:00
										 |  |  | mixinFlat(<base>, <object>, ..) | 
					
						
							|  |  |  | 	-> <base> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | This is like `Object.assign(..)` but copies property descriptors rather  | 
					
						
							|  |  |  | than property values. | 
					
						
							| 
									
										
										
										
											2020-04-25 01:43:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | ### `RawInstance(..)`
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +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-08 18:36:51 +03:00
										 |  |  | RawInstance(<context>, <constructor>, ..) | 
					
						
							| 
									
										
										
										
											2020-04-26 19:30:49 +03:00
										 |  |  | 	-> <object> | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | `RawInstance(..)` will do the following: | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | - Create an instance object | 
					
						
							|  |  |  | 	- get result of `.__new__(..)` if defined, or | 
					
						
							|  |  |  | 	- if prototype is a function or `.__call__(..)` is defined, create a  | 
					
						
							|  |  |  | 	  wrapper function, or | 
					
						
							| 
									
										
										
										
											2020-05-17 22:57:25 +03:00
										 |  |  | 	- if constructor's `.__proto__` has a `.__rawinstance__(..)` use it | 
					
						
							|  |  |  | 	  to create an instance, or | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | 	- if constructor's `.__proto__` is a function (constructor) use it  | 
					
						
							|  |  |  | 	  to create an instance, or | 
					
						
							| 
									
										
										
										
											2020-05-06 14:32:00 +03:00
										 |  |  | 	- use `{}`. | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | - Link the object into the prototype chain | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 18:42:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 04:24:09 +03:00
										 |  |  | _Un-initialized_ means this will not call `.__init__(..)` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 18:44:13 +03:00
										 |  |  | `RawInstance(..)` can be called with and without `new`. | 
					
						
							| 
									
										
										
										
											2020-05-08 18:42:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | ### `Constructor(..)` / `C(..)`
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:37:46 +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>) | 
					
						
							| 
									
										
										
										
											2020-05-06 03:39:32 +03:00
										 |  |  | Constructor(<name>, <parent-constructor>, <constructor-mixin>, <prototype>) | 
					
						
							| 
									
										
										
										
											2020-05-03 03:03:18 +03:00
										 |  |  | Constructor(<name>, <constructor-mixin>, <prototype>) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:48:55 +03:00
										 |  |  | 	-> <constructor> | 
					
						
							| 
									
										
										
										
											2019-07-16 23:49:32 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | `Constructor(..)` essentially does the following: | 
					
						
							|  |  |  | - Creates a _constructor_ function, | 
					
						
							|  |  |  | - Sets constructor `.name` and `.toString(..)` for introspection, | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | - Creates `.__rawinstance__(..)` wrapper to `RawInstance(..)` | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  | - Sets constructor `.__proto__`, `.prototype` and `.prototype.constructor`, | 
					
						
							|  |  |  | - Mixes in _constructor-mixin_ if given. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The resulting _constructor_ function when called will: | 
					
						
							| 
									
										
										
										
											2020-05-08 18:36:51 +03:00
										 |  |  | - call constructor's `.__rawinstance__(..)` if defined or `RawInstance(..)`  | 
					
						
							| 
									
										
										
										
											2020-05-06 14:30:32 +03:00
										 |  |  |   to create an instance, | 
					
						
							|  |  |  | - call instance's `.__init__(..)` if present. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-30 16:41:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 18:29:22 +03:00
										 |  |  | Note that `Constructor(<name>, <prototype>)` is intentionally set as default | 
					
						
							|  |  |  | instead of having the _parent-constructor_ as the last argument, this is  | 
					
						
							|  |  |  | done for two reasons: | 
					
						
							|  |  |  | - The main cause to inherit from a constructor is to extend it, | 
					
						
							|  |  |  | - In real code the `Constructor(<name>, <prototype>)` is more common than | 
					
						
							|  |  |  |   empty inheritance. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-08 18:44:13 +03:00
										 |  |  | `Constructor(..)` / `C(..)` can be called with and without `new`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Utilities
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 15:53:24 +03:00
										 |  |  | ### `normalizeIndent(..)` / `normalizeTextIndent(..)`
 | 
					
						
							| 
									
										
										
										
											2020-05-06 14:54:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 15:42:32 +03:00
										 |  |  | Align _code_ to shortest leading white-space | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | normalizeIndent(<text>) | 
					
						
							|  |  |  | normalizeIndent(<text>, <tab-size>) | 
					
						
							| 
									
										
										
										
											2020-05-08 15:42:32 +03:00
										 |  |  | normalizeIndent(<text>, <tab-size>, <keep-tabs>) | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | 	-> <text> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is used to format `.toString(..)` return values for nested functions | 
					
						
							|  |  |  | to make source printing in console more pleasant to read. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 15:53:24 +03:00
										 |  |  | `tab_size` defaults to `object.TAB_SIZE` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `keep_tabs` defaults to `object.KEEP_TABS` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 16:03:02 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-08 16:03:37 +03:00
										 |  |  | A shorthand to `normalizeIndent(..)` optimized for text rather than code | 
					
						
							| 
									
										
										
										
											2020-05-08 16:03:02 +03:00
										 |  |  | ``` | 
					
						
							|  |  |  | normalizeTextIndent(..) | 
					
						
							|  |  |  | 	-> <text> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This ignores `object.KEEP_TABS` and `keep_tabs` is 0 by default. | 
					
						
							| 
									
										
										
										
											2020-05-08 15:53:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | ### `match(..)`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Test if the two objects match in attributes and attribute values | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | match(base, obj) | 
					
						
							|  |  |  | 	-> bool | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:20:20 +03:00
										 |  |  | This relies on first level object structure to match the input object, for  | 
					
						
							|  |  |  | a successful match one of the following must apply: | 
					
						
							|  |  |  | - object are identical | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 21:20:20 +03:00
										 |  |  | or: | 
					
						
							|  |  |  | - `typeof` matches _and_, | 
					
						
							|  |  |  | - attribute count matches _and_, | 
					
						
							|  |  |  | - attribute names match _and_, | 
					
						
							|  |  |  | - attribute values are identical. | 
					
						
							| 
									
										
										
										
											2020-05-07 21:02:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 03:11:36 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-24 23:59:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 01:14:00 +03:00
										 |  |  | <!-- vim:set ts=4 sw=4 spell : --> |