Initializers

You can add initializers (aka constructors) to your stamps.

const Logger = stampit({
  init({level = 50}) {
    this.level = level
  }
})

const logger = Logger({ level: 42 })

logger.level === 42

Each initializer will be executed on object creation. (But the list of initializers is always deduplicated.)

const Server = stampit(Logger, {
  init({ port = process.env.PORT }) {
    this.port = port
  }
})

const server = Server({ port: 6666 })

server.level === 50
server.port === 6666

If you return anything from an initializer then it becomes the object instance.

const NullServer = Server.init(function () {
  return null
})

const server = NullServer()

server === null

Descriptor merging algorithm

The initializers are concatenated into a deduplicated array. As the result, the order of composition becomes the order of initializer execution.

const {init} = stampit

const Log1 = init(() => console.log(1))
const Log2 = init(() => console.log(2))
const Log3 = init(() => console.log(3))

const MultiLog = stampit(Log1, Log2, Log3)

MultiLog() // Will print three times:
// 1
// 2
// 3

// because there are 3 initializers
MultiLog.compose.initializers.length === 3

Stamps remove duplicate initializers.

const {init} = stampit

const func = () => console.log(1)
const Log1 = init(func)
const Log2 = init(func)
const Log3 = init(func)

const MultiLog = stampit(Log1, Log2, Log3)

MultiLog() // Will print only once:
// 1

// because there is only one initializer
MultiLog.compose.initializers.length === 1

Initializer arguments

NOTE

Parameter - a variable being passed to a function.

Argument - a variable received by a function.

You can pass multiple parameters to your stamp while creating an object. First parameter passed as is to all initializers. But the rest of the parameters are available inside the {args} property of the second initializer argument.

const MultiArg = stampit({
  init(arg1, { args }) {
    arg1 === 'foo'
    args[0] === arg1  // first argument of the initializer is passed from factory first parameter
    args[0] === 'foo'
    args[1] === 'BAR'
    args[2] === 'thing'
  }
})

MultiArg('foo', 'BAR', 'thing')

If there is no first parameter then an empty object is passed as the first argument.

const NoException = stampit({
  init({ iAmUndefined }) { // won't throw exception in this line
    iAmUndefined === undefined
    console.log(arguments[0]) // will print empty object: {}
  }
})

NoException(/* nothing here! */)

Every initializer second argument is always this object: { stamp, args, instance }. Where:

  • stamp is the stamp which was used to create this object. Useful to retrieve stamp's metadata (aka descriptor).

  • args the parameters passed to the stamp while creating the object.

  • instance the object instance itself. Always equals this context of the initializer.

const PrintMyArgs = stampit({
  init(_, { stamp, args, instance }) {
    console.log('Creating object from this stamp:', stamp)
    console.log('List of arguments:', args)
    console.log('Object instance:', instance)

    this === instance
  }
})

Other ways to add initializers

Exactly the same stamp can be created in few ways. Here they all are.

function myInitializer ({ level = 50 }) {
  this.level = level
}

const Logger = stampit({
  init: myInitializer
})

const Logger = stampit({
  init: [myInitializer]
})

const Logger = stampit({
  initializers: myInitializer
})

const Logger = stampit({
  initializers: [myInitializer]
})

const Logger = stampit.init(myInitializer)
const Logger = stampit.init([myInitializer])
const Logger = stampit.initializers(myInitializer)
const Logger = stampit.initializers([myInitializer])

const Logger = stampit().init(myInitializer)
const Logger = stampit().init([myInitializer])
const Logger = stampit().initializers(myInitializer)
const Logger = stampit().initializers([myInitializer])

Last updated