joint.all.js
function merge(object) {
      var args = arguments,
          length = 2;

      if (!isObject(object)) {
        return object;
      }
      // allows working with `_.reduce` and `_.reduceRight` without using
      // their `index` and `collection` arguments
      if (typeof args[2] != 'number') {
        length = args.length;
      }
      if (length > 3 && typeof args[length - 2] == 'function') {
        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
      } else if (length > 2 && typeof args[length - 1] == 'function') {
        callback = args[--length];
      }
      var sources = nativeSlice.call(arguments, 1, length),
          index = -1,
          stackA = getArray(),
          stackB = getArray();

      while (++index < length) {
        baseMerge(object, sources[index], callback, stackA, stackB);
      }
      releaseArray(stackA);
      releaseArray(stackB);
      return object;
    }
function merge(object) {
      var args = arguments,
          length = 2;

      if (!isObject(object)) {
        return object;
      }
      // allows working with `_.reduce` and `_.reduceRight` without using
      // their `index` and `collection` arguments
      if (typeof args[2] != 'number') {
        length = args.length;
      }
      if (length > 3 && typeof args[length - 2] == 'function') {
        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
      } else if (length > 2 && typeof args[length - 1] == 'function') {
        callback = args[--length];
      }
      var sources = nativeSlice.call(arguments, 1, length),
          index = -1,
          stackA = getArray(),
          stackB = getArray();

      while (++index < length) {
        baseMerge(object, sources[index], callback, stackA, stackB);
      }
      releaseArray(stackA);
      releaseArray(stackB);
      return object;
    }
Recursively merges own enumerable properties of the source object(s), that
don't resolve to `undefined` into the destination object. Subsequent sources
will overwrite property assignments of previous sources. If a callback is
provided it will be executed to produce the merged values of the destination
and source properties. If the callback returns `undefined` merging will
be handled by the method instead. The callback is bound to `thisArg` and
invoked with two arguments; (objectValue, sourceValue).

@static
@memberOf _
@category Objects
@param {Object} object The destination object.
@param {...Object} [source] The source objects.
@param {Function} [callback] The function to customize merging properties.
@param {*} [thisArg] The `this` binding of `callback`.
@returns {Object} Returns the destination object.
@example

var names = {
'stooges': [
{ 'name': 'moe' },
{ 'name': 'larry' }
]
};

var ages = {
'stooges': [
{ 'age': 40 },
{ 'age': 50 }
]
};

_.merge(names, ages);
// => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }

var food = {
'fruits': ['apple'],
'vegetables': ['beet']
};

var otherFood = {
'fruits': ['banana'],
'vegetables': ['carrot']
};

_.merge(food, otherFood, function(a, b) {
return _.isArray(a) ? a.concat(b) : undefined;
});
// => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }