Package Exports
- ig-object
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ig-object) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
object.js
object.js provides a set of tools for making and maintaining object constructors and for managing their inheritance relations.
This is an alternative to the ES6 class
syntax in JavaScript and provides
several advantages:
- Simple way to define instance and "class" methods, properties and attributes,
- Uniform and minimalistic definition syntax based on basic JavaScript object syntax, no special cases, special syntax or "the same but slightly different" ways to do things,
- Transparently based on JavaScript's prototypical inheritance model,
- Granular instance construction (a-la Python's
.__new__(..)
and.__init__(..)
methods) - Simple way to define callable instances (including a-la Python's
.__call__(..)
) - Less restrictive:
new
is optional- all input components are reusable
- no artificial restrictions
Disadvantages compared to the class
syntax:
- No syntactic sugar
- Slightly more complicated calling of
parent
(super) methods
Installation
$ npm install ig-object
Or just download and drop object.js into your code.
Basic usage
Include the code, this is compatible with both node's and
RequireJS' require(..)
var object = require('ig-object')
Create a basic constructor...
// NOTE: new is optional here...
var A = new object.Constructor('A')
In JavaScript constructor B
inherits from constructor A
iff
B.prototype
is prototype of A.prototype
. So to implement inheritance
we simply need to link the prototypes of two constructors via .__proto__
,
Object.create(..)
or other means.
var B = object.Constructor('B', {__proto__: A.prototype})
var C = object.Constructor('C', Object.create(B.prototype))
var c = C() // or new C()
c instanceof C // -> true
c instanceof B // -> true
c instanceof A // -> true
Inheritance
//
// Base <--- Item
//
var Base = object.Constructor('Base', {
proto_attr: 'prototype attr value',
get prop(){
return 'propery value' },
method: function(){
console.log('Base.method()') },
// initializer...
__init__: function(){
this.instance_attr = 'instance'
},
})
var Item = object.Constructor('Item', {
// inherit from Base...
__proto__: Base.prototype,
__init__: function(){
// call the "super" method...
object.parentCall(this.prototype.__init__, this)
this.item_attr = 'instance attribute value'
},
})
Callable instances
var Action = object.Constructor('Action',
// constructor as a function...
function(context, ...args){
// return the instance...
return this
})
var action = new Action()
// the instance now is a function...
action()
// a different way to do the above...
//
// 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.
var Action2 = object.Constructor('Action2', {
__call__: function(context, ...args){
return this
},
})
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:
- Internal context (
this
)
This always references the instance being called - External context (
context
)
This is the object the instance is called from, i.e. the call context (window
orglobal
by default)
If the prototype is explicitly defined as a function then it is the
user's responsibility to call .__call__(..)
method.
Low level constructor
var LowLevel = object.Constructor('LowLevel', {
__new__: function(context, ...args){
return {}
},
})
Like function constructor and .__call__(..)
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.
The external context is the same as above.
Contexts:
- Internal context (
this
)
References the.prototype
of the constructor. - External context (
context
)
This is the object the instance is called from, i.e. the call context (window
orglobal
by default), the same as for function constructor and.__call__(..)
.
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
take care of both the function constructor and prototype.__call__(..)
handling.
Notes:
.__new__(..)
is an instance method, contrary to Python (the inspiration for this protocol). This is done intentionally as in JavaScript there is no distinction between an instance and a class and defining.__new__(..)
in the class would both add complexity as well as restrict the use-cases for the constructor.
Components
Get sources for attribute
sources(<object>, <name>)
sources(<object>, <name>, <callback>)
-> <list>
Get parent method
parent(<method>, <this>)
-> <parent-method>
-> undefined
parent(<prototype>, <name>, <this>)
-> <parent-value>
-> undefined
Get parent method and call it
parentCall(<method>, <this>)
parentCall(<prototype>, <name>, <this>)
-> <result>
-> undefined
Mixin objects into a prototype chain
mixin(<root>, <object>, ...)
-> <object>
Mixin contents of objects into one
mixinFlat(<root>, <object>, ...)
-> <object>
This is like Object.assign(..)
but copies property objects rather than
property values.
Make a raw (un-initialized) instance
makeRawInstance(<context>, <constructor>, ...)
-> <object>
EXPERIMENTAL: a shorthand to this is defined as Constructor.__rawinstance__(..)
Define an object constructor
Constructor(<name>, <prototype>)
Constructor(<name>, <class-prototype>, <prototype>)
-> <constructor>
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.
License
Copyright (c) 2019, Alex A. Naanou,
All rights reserved.