State.js is a JavaScript library for embedding composable, heritable first-class states into arbitrary owner objects.
The exported state function will be used here in two ways: (1) to define structures called state expressions, which describe behavior in terms of methods, data, events, etc.; and (2) to implement a composite state expression on an owner, producing a tree of States that belong to the owner and describe its potential exhibited behaviors.
The implementing form has two effects: (1) the owner is given a new state method, which closes over the owner’s new state tree and serves as the accessor to its States; and (2) for any method defined at least once in the state tree, a corresponding dispatcher method is created and added to the owner.
Hierarchical single-inheritance is provided by the superstate–substate relation, which defines a state tree rooted from the owner’s unique root state.
Compositional multiple-inheritance is provided simultaneously by parastates. The parastate and superstate ancestors of a State are C3–linearized into a monotonic, unambiguous resolution order.
Indirect prototypal inheritance is also defined by the protostate–epistate relation, an implication of the owner’s prototype chain.
Attributes are a set of keyword strings that may precede the body of a state expression. These concisely empower or constrain certain aspects of a State, such as abstraction, destination, and mutability.
State methods express or override behavior of the owner. Method calls received by the owner are dispatched to its current state’s own or inherited implementation of the corresponding method.
By default, state methods are invoked in the context of the owner, just like normal methods. To gain insight into its place in the owner’s state tree, a method definition can instead be contextually bound to the State for which the method acts. (This will be the State in which the method is defined, unless the method is inherited from a protostate, in which case the context will be the inheriting epistate.)
A state method can also be wrapped in a decorator that fixes the method with bindings to the precise State where it is defined (invariant across the protostate–epistate relation).
State instances are nominally immutable by default. This restriction forces any changes in the owner’s State-based behavior to be expressed in terms of transitions between States.
Alternatively, a State may be explicitly expressed as mutable, such that modular pieces of behavior may be inserted and implemented dynamically into a live State, thereby allowing changes in behavior to be exhibited via mutations as well.
A free bit of behavior can be expressed with just a plain object.
This factory produces a boxed function that will instill an enclosed behavior into a receiving State.
A traveler assimilates itself by overwriting previously defined behavior with the appropriately chosen new behavior.
A Transition instance is an ephemeral type of State that is automatically created and occupied as an owner’s current state while it is in the process of moving between States.