walk = function (value, dst, visited, reference) {
    if (_.isObject(value) && !_.isFunction(value)) {
      const proto = Object.getPrototypeOf(value);
      const keys = Object.keys(value);
      for (let i = 0, il = keys.length; i < il; i++) {
        const key = keys[i];
        const property = value[key];
        if (!_.isFunction(property) && proto[key] !== property && (filter == null || filter(key, property))) {
          const index = _.indexOf(visited, property);
          if (index !== -1) {
            dst[key] = reference[index];
          } else {
            let next;
            if (_.isArray(property)) {
              next = dst[key] = [];
            } else if (_.isObject(property)) {
              next = dst[key] = {};
            } else {
              next = dst[key] = property;
            }
            visited.push(property);
            reference.push(next);
            if (_.isObject(property)) {
              walk(property, next, visited, reference);
            }
          }
        }
      }

      if (post != null) {
        post(value, dst);
      }
    }
  }
Makes a deep copy of an object, ignoring functions and properties that match the prototype.
@param {Object|Array} source
@param {Function} [filter=null] filter method that receives key and property and should return true or false
@param {Function} [post=null] post copy method that receives the current value being copied and the current destination object to copy into
@returns {Object|Array}