JSPM

  • Created
  • Published
  • 0
  • Score
    100M100P100Q56917F
  • License BSD-3-Clause

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 or global 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 or global 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

BSD 3-Clause License

Copyright (c) 2019, Alex A. Naanou,
All rights reserved.