I like Douglas Crockford's "Class Free OOP" approach for managing dependencies and composing functions:
function constructor(spec) {
let {member} = spec,
{other} = other_constructor(spec),
method = function () {
// accesses member, other, method, spec
};
return Object.freeze({
method,
other
});
}
but prefer to use an immutable data structure instead of Object.freeze().All application state can be stored in a single "Atom" (i.e immutable data) and all message passing can be achieved through CSP channels.
When dealing with the DOM, 'incremental-dom' is a nice option.
Of course, separating pure functions from side-effects inducing code is key to maintaining control.
This is my approach when going "framework-less".