<!-- Documentation snapshot: package 5.0.0-beta.1; channel next; base revision b06750c507494441f0b2298766b70087e45346a2; local changes false; original source SHA-256 056bb3041902d66831a0031e2e9c97770f485f613450861ae55aba46ca592243. -->

# Marionette.MnObject

Use `MnObject` for objects that need Marionette events and cleanup without a
DOM element. It provides `initialize`, options, the Events API, a unique `cid`,
and `extend`, with no Backbone dependency.

`MnObject` includes:
- [Common Marionette Functionality](/docs/common.md)
- [Class Events](/docs/class-events.md#mnobject-events)
- [Radio API](/docs/radio.md#marionette-integration)
- [State ownership](/docs/state.md#borrowed-and-owned-sources)

## Documentation Index

* [Instantiating a MnObject](#instantiating-a-mnobject)
* [Unique Client ID](#unique-client-id)
* [Destroying a MnObject](#destroying-a-mnobject)
* [Basic Use](#basic-use)
* [v4 Migration](#v4-migration)

## Instantiating a MnObject

Constructor options are shallow-copied into `this.options`. Own enumerable
`channelName`, `radioEvents`, `radioRequests`, and `stateEvents` options with values other than
`undefined` are also attached directly to the instance. Other options remain
available through `this.options` and `getOption` unless explicitly merged.
The channel options use Marionette's built-in [`Radio`](/docs/radio.md); see that guide
for the separate `backbone.radio` migration boundary.

A supplied `state` source is borrowed. A source returned by `createState(options)`
is owned and created lazily; `getState()` returns the exact source. Configured
`stateEvents` subscribe after `initialize`. Destruction removes those
subscriptions and disposes owned State through the selected StateApi. See
[State](/docs/state.md) before enabling observable State events.

```javascript
import { MnObject } from 'marionette';

const myObject = new MnObject({ channelName: 'tasks' });

myObject.channelName; // 'tasks'
```

## Unique Client ID
The `cid` or client id is a unique identifier automatically assigned to MnObjects
when they're first created and by default is prefixed with `mno`.
You can modify the prefix for `MnObject`s you `extend` by setting the `cidPrefix`,
which should be a non-empty string when customized. IDs generated with the same
prefix by one loaded copy of Marionette are unique, including when different
Marionette types use that prefix. Treat the complete `cid` as opaque: its numeric
suffix and allocation order are not API, and its sequence is not coordinated with
IDs generated by Underscore or Backbone.
The [v4-to-v5 migration ledger](/docs/migration-from-v4.md#compatibility-ledger)
records the sequence-ownership rationale.

```javascript
import { MnObject } from 'marionette';

const MyFoo = MnObject.extend({
  cidPrefix: 'foo'
});

const foo = new MyFoo();

foo.cid.startsWith('foo'); // true
```

## Destroying a MnObject

### `destroy`
On successful completion of its lifecycle, `destroy` removes subscriptions the
instance made with `listenTo`, releases its owned Radio event subscriptions and
replies, cleans up State, and returns the MnObject synchronously. Returned Promises
from destruction hooks are not awaited. It does not reset the shared Radio channel or
remove unrelated channel handlers. Listeners registered directly on the
instance with `on` are not removed automatically. If a lifecycle callback
throws, cleanup that has not yet run may be skipped; the failure boundaries are
described below.

Invoking `destroy` triggers `before:destroy` and `destroy` events and their
[corresponding `onBeforeDestroy` and `onDestroy` methods](/docs/events.md#onevent-binding).
Each receives the MnObject followed by the `options` passed to `destroy`.

While a `destroy()` call is in progress, nested calls from either lifecycle
event return the same MnObject without restarting teardown. Calls after
destruction also return the same MnObject without repeating the lifecycle.
`Application` has an asynchronous destruction lifecycle; see its
[reference](/docs/application.md#application-lifecycle).
`isDestroyed()` is `false` during `before:destroy` and `true` during `destroy`.
If a lifecycle handler throws, the error propagates and stops destruction.
The destruction guard remains set; later `destroy()` calls do not restart
hooks or resume cleanup.

A custom override that mutates owned state before calling the base `destroy`
method is outside this guard. See the
[v4-to-v5 compatibility ledger](/docs/migration-from-v4.md#compatibility-ledger) for
the override boundary.

```javascript
import { MnObject } from 'marionette';

// define a mnobject with an onBeforeDestroy method
const MyObject = MnObject.extend({

  onBeforeDestroy(currentObject, options) {
    // put other custom clean-up code here
  }
});

// create new MnObject instances
const obj = new MyObject();
const source = new MnObject();

// add some event handlers
obj.on('before:destroy', function(currentObject, options) {
  console.log(options.foo);
});
obj.listenTo(source, 'bar', function() {});

// trigger the lifecycle and stop listening to source
obj.destroy({ foo: 'bar' });
```

### `isDestroyed`

This method will return a boolean indicating if the mnobject has been destroyed.

```javascript
import { MnObject } from 'marionette';

const obj = new MnObject();
obj.isDestroyed(); // false
obj.destroy();
obj.isDestroyed(); // true
```

## Basic Use

Selections is a simple MnObject that manages a selection of things.
Because Selections extends from MnObject, it inherits `initialize` and the
[Events API](/docs/events.md).

```javascript
import { MnObject } from 'marionette';

const Selections = MnObject.extend({

  initialize() {
    this.selections = {};
  },

  select(key, selection) {
    this.selections[key] = selection;
    this.triggerMethod('select', key, selection);
  },

  deselect(key, selection) {
    delete this.selections[key];
    this.triggerMethod('deselect', key, selection);
  }

});

const selections = new Selections();
const truck = { name: 'Dump truck' };

// use the inherited Events API
selections.on('select', function(key, selection) {
  console.log(selection);
});

selections.select('toy', truck);
```

## v4 Migration

v5 exports `MnObject` by name from `marionette`. The historical `Object` alias
and v4 default namespace export are removed. See the
[v4-to-v5 migration ledger](/docs/migration-from-v4.md) for the replacement paths.


[Canonical source](/docs/markdown/docs/marionette.mnobject.md) · [Source identity](/docs/manifest.json)
