Edit in JSFiddle

var $loops = document.getElementById('loops');
var $draws = document.getElementById('draws');
var $updates = document.getElementById('updates');
var $state = document.getElementById('state');

//only attaching to window so the onclick works in jsfiddle
window.states = (function () {
    function State(obj) {
        var _paused;
        var _running;
        var _object = obj;

        this.update = function (time) {
            if (_object.update) {
                _object.update.call(this, time);
            }
        };

        this.draw = function (time) {
            if (_object.draw) {
                _object.draw.call(this, time);
            }
        };

        this.init = function () {
            _running = true;
            _paused = false;
            if (_object.init) {
                _object.init.call(this);
            }
        };

        this.start = function () {
            if (_object.start) {
                _object.start.call(this);
            }
        };

        this.stop = function () {
            if (_object.stop) {
                _object.stop.call(this);
            }
        };

        this.quit = function () {
            _running = false;
        };

        this.pause = function () {
            _paused = !_paused;
        };

        this.isRunning = function () {
            return _running;
        };

        this.isPaused = function () {
            return _paused;
        };

        this.name = obj.name;
    }

    function StateMachine() {
        var _states = {};

        this.active = null;

        this.add = function (state) {
            state = state || {};
            if(typeof state.name === 'undefined') {
                //error
            }
            _states[state.name] = new State(state);
            _states[state.name].init();
            if (this.active === null) {
                this.active = _states[state.name];
            }
        };

        this.switch = function (name) {
            if (_states[name]) {
                $state.innerHTML += 'STATEMACHINE: switching to a new state: '+name+'<br>';
                this.active.stop();
                this.active = _states[name];
                this.active.start();
            } else {
                //throw an error
            }
        };
    }

    return new StateMachine();
})();

states.add({
    name: 'start',
    init: function() {
        $state.innerHTML += 'START STATE: init <br>';  
    },
    start: function () {
        $state.innerHTML += 'START STATE: starting <br>';
        window.setTimeout(function () {
            window.states.switch('play');
        }, 2000);
    }
});


states.add({
    name: 'play',
    init: function () {
        $state.innerHTML += 'PLAY STATE: init <br>';
    },
    start: function() {
        $state.innerHTML += 'PLAY STATE: starting <br>';
    },
    update: function () {
        $loops.innerHTML = parseInt($loops.innerHTML) + 1
    }
});

states.add({
    name: 'stop',
    init: function () {
        $state.innerHTML += 'STOP STATE: init<br>';
        this.quit()
    },
    start: function() {
        $state.innerHTML += 'STOP STATE: starting<br>';
        this.quit()        
    }
});

window.engine = {
    start: function (state) {
        $state.innerHTML += 'ENGINE: starting<br>';
        engine.running = true;
        states.switch(state);
        engine.loop(0);
    },
    stop: function () {
        $state.innerHTML += 'ENGINE: stopping<br>';
        $loops.innerHTML = 0;
        $draws.innerHTML = 0;
        $updates.innerHTML = 0;
    },
    loop: function (time) {
        if (states.active.isPaused() === false) {
            engine.update(time);
        }
        engine.draw(time);
        if (states.active.isRunning() === true) {
            window.requestAnimationFrame(function (time) {
                engine.loop(time);
            });
        } else {
            engine.stop();
        }
    },
    update: function (time) {
        states.active.update(time);
    },
    draw: function (time) {
        states.active.draw(time);
    },
    pause: function () {
        states.active.pause();
    }
};
<button type="button" onclick="engine.start('start')">Start</button>
<button type="button" onclick="states.switch('stop')">Stop</button>
<br />PLAY STATE: updates <span id="loops">0</span>
<br /><br />
<div id="state"></div>