# Initializers

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

```javascript
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.)*

```javascript
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.

```javascript
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**.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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])
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://stampit.js.org/api/initializers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
