function init(options) {
  if (typeof options === 'string') {
    options = {actorId: options}
  } else if (typeof options === 'undefined') {
    options = {}
  } else if (!isObject(options)) {
    throw new TypeError(`Unsupported value for init() options: ${options}`)
  }

  if (!options.deferActorId) {
    if (options.actorId === undefined) {
      options.actorId = uuid()
    }
    checkActorId(options.actorId)
  }

  if (options.observable) {
    const patchCallback = options.patchCallback, observable = options.observable
    options.patchCallback = (patch, before, after, local, changes) => {
      if (patchCallback) patchCallback(patch, before, after, local, changes)
      observable.patchCallback(patch, before, after, local, changes)
    }
  }

  const root = {}, cache = {_root: root}
  const state = {seq: 0, maxOp: 0, requests: [], clock: {}, deps: []}
  if (options.backend) {
    state.backendState = options.backend.init()
    state.lastLocalChange = null
  }
  Object.defineProperty(root, OBJECT_ID, {value: '_root'})
  Object.defineProperty(root, OPTIONS,   {value: Object.freeze(options)})
  Object.defineProperty(root, CONFLICTS, {value: Object.freeze({})})
  Object.defineProperty(root, CACHE,     {value: Object.freeze(cache)})
  Object.defineProperty(root, STATE,     {value: Object.freeze(state)})
  return Object.freeze(root)
}
Creates an empty document object with no changes.