*
@method merge(<target>, <source>, [deep] = false, [resolve] = true)
@returns Merged object
@short Merges all the properties of <source> into <target>.
@extra Merges are shallow unless [deep] is %true%. Properties of <source> will win in the case of conflicts, unless [resolve] is %false%. [resolve] can also be a function that resolves the conflict. In this case it will be passed 3 arguments, %key%, %targetVal%, and %sourceVal%, with the context set to <source>. This will allow you to solve conflict any way you want, ie. adding two numbers together, etc. %merge% is available as an instance method on extended objects.
@example

Object.merge({a:1},{b:2}) -> { a:1, b:2 }
Object.merge({a:1},{a:2}, false, false) -> { a:1 }
+   Object.merge({a:1},{a:2}, false, function(key, a, b) {
return a + b;
}); -> { a:3 }
Object.extended({a:1}).merge({b:2}) -> { a:1, b:2 }

*
function(target, source, deep, resolve) {
      var key, val;
      // Strings cannot be reliably merged thanks to
      // their properties not being enumerable in < IE8.
      if(target && typeof source != 'string') {
        for(key in source) {
          if(!hasOwnProperty(source, key) || !target) continue;
          val = source[key];
          // Conflict!
          if(isDefined(target[key])) {
            // Do not merge.
            if(resolve === false) {
              continue;
            }
            // Use the result of the callback as the result.
            if(isFunction(resolve)) {
              val = resolve.call(source, key, target[key], source[key])
            }
          }
          // Deep merging.
          if(deep === true && val && isObjectPrimitive(val)) {
            if(isDate(val)) {
              val = new date(val.getTime());
            } else if(isRegExp(val)) {
              val = new regexp(val.source, getRegExpFlags(val));
            } else {
              if(!target[key]) target[key] = array.isArray(val) ? [] : {};
              object.merge(target[key], source[key], deep, resolve);
              continue;
            }
          }
          target[key] = val;
        }
      }
      return target;
    }