All files / src/helpers extend.js

100% Statements 4/4
54.17% Branches 13/24
100% Functions 0/0
100% Lines 4/4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119                                                                                                                9x 9x 9x 9x                                                                                                                      
/**
 * A port of jQuery's extend. Merge the contents of two or more objects together into the first object. Supports deep extending with `true` as the first argument.
 *
 * @function extend
 * @param {Boolean} [deepExtend] Optional, set to `true` to merge recursively.
 * @param {Object} destination The object to modify
 * @param {Object} source The object whose keys to take
 * @param {Object} [source2] Optional, You can add any number of objects as arguments.
 * @returns {Object} result The merged object. Note that the `destination` object will always be modified.
 *
 * @example
 * var mergedObj = io.extend({}, {name: 'indian-ocean'}, {alias: 'io'})
 * console.log(mergedObj)
 * // {
 * //   name: 'indian-ocean',
 * //   alias: 'io'
 * // }
 *
 * var name = {name: 'indian-ocean'}
 * io.extend(name, {alias: 'io'})
 * console.log(name)
 * // {
 * //   name: 'indian-ocean',
 * //   alias: 'io'
 * // }
 *
 * @example
 * var object1 = {
 *   apple: 0,
 *   banana: { weight: 52, price: 100 },
 *   cherry: 97
 * }
 * var object2 = {
 *   banana: { price: 200 },
 *   almond: 100
 * }
 * io.extend(true, object1, object2)
 * console.log(object1)
 * //  {
 * //   apple: 0,
 * //   banana: {
 * //     weight: 52,
 * //     price: 200
 * //   },
 * //   cherry: 97,
 * //   almond: 100
 * // }
 *
 */
export default function extend () {
  var options
  var name
  var src
  var copy
  var copyIsArray
  var clone
  var target = arguments[0] || {}
  var i = 1
  var length = arguments.length
  var deep = false
 
  // Handle a deep copy situation
  if (typeof target === 'boolean') {
    deep = target
 
    // Skip the boolean and the target
    target = arguments[i] || {}
    i++
  }
 
  // Handle case when target is a string or something (possible in deep copy)
  if (typeof target !== 'object' && typeof target !== 'function') {
    target = {}
  }
 
  // Extend indian-ocean itself if only one argument is passed
  if (i === length) {
    target = this
    i--
  }
 
  for (; i < length; i++) {
    // Only deal with non-null/undefined values
    if ((options = arguments[i]) != null) {
      // Extend the base object
      for (name in options) {
        src = target[name]
        copy = options[name]
 
        // Prevent never-ending loop
        if (target === copy) {
          continue
        }
 
        // Recurse if we're merging plain objects or arrays
        if (deep && copy && (typeof copy === 'object') ||
            (copyIsArray = Array.isArray(copy))) {
          if (copyIsArray) {
            copyIsArray = false
            clone = src && Array.isArray(src) ? src : []
          } else {
            clone = src && typeof src === 'object' ? src : {}
          }
 
          // Never move original objects, clone them
          target[name] = extend(deep, clone, copy)
 
          // Don't bring in undefined values
        } else if (copy !== undefined) {
          target[name] = copy
        }
      }
    }
  }
 
  // Return the modified object
  return target
}