copy (from, to, stackFrom, stackTo, blacklist, plain) {
    if (!to) {
      to = from
      if (from) {
        if (utils.isArray(from)) {
          to = utils.copy(from, [], stackFrom, stackTo, blacklist, plain)
        } else if (utils.isDate(from)) {
          to = new Date(from.getTime())
        } else if (utils.isRegExp(from)) {
          to = new RegExp(from.source, from.toString().match(/[^/]*$/)[0])
          to.lastIndex = from.lastIndex
        } else if (utils.isObject(from)) {
          if (plain) {
            to = utils.copy(from, {}, stackFrom, stackTo, blacklist, plain)
          } else {
            to = utils.copy(
              from,
              Object.create(Object.getPrototypeOf(from)),
              stackFrom,
              stackTo,
              blacklist,
              plain
            )
          }
        }
      }
    } else {
      if (from === to) {
        throw utils.err(`${DOMAIN}.copy`)(
          500,
          'Cannot copy! Source and destination are identical.'
        )
      }

      stackFrom = stackFrom || []
      stackTo = stackTo || []

      if (utils.isObject(from)) {
        const index = stackFrom.indexOf(from)
        if (index !== -1) {
          return stackTo[index]
        }

        stackFrom.push(from)
        stackTo.push(to)
      }

      let result
      if (utils.isArray(from)) {
        let i
        to.length = 0
        for (i = 0; i < from.length; i++) {
          result = utils.copy(
            from[i],
            null,
            stackFrom,
            stackTo,
            blacklist,
            plain
          )
          if (utils.isObject(from[i])) {
            stackFrom.push(from[i])
            stackTo.push(result)
          }
          to.push(result)
        }
      } else {
        if (utils.isArray(to)) {
          to.length = 0
        } else {
          utils.forOwn(to, function (value, key) {
            delete to[key]
          })
        }
        for (var key in from) {
          if (Object.hasOwnProperty.call(from, key)) {
            if (utils.isBlacklisted(key, blacklist)) {
              continue
            }
            result = utils.copy(
              from[key],
              null,
              stackFrom,
              stackTo,
              blacklist,
              plain
            )
            if (utils.isObject(from[key])) {
              stackFrom.push(from[key])
              stackTo.push(result)
            }
            to[key] = result
          }
        }
      }
    }
    return to
  }
Deep copy a value.

@example
import { utils } from 'js-data';
const a = { foo: { bar: 'baz' } };
const b = utils.copy(a);
a === b; // false
utils.areDifferent(a, b); // false

@param {*} from Value to deep copy.
@param {*} [to] Destination object for the copy operation.
@param {*} [stackFrom] For internal use.
@param {*} [stackTo] For internal use.
@param {string[]|RegExp[]} [blacklist] List of strings or RegExp of
properties to skip.
@param {boolean} [plain] Whether to make a plain copy (don't try to use
original prototype).
@returns {*} Deep copy of `from`.
@since 3.0.0