mixin.js
 1  var arrayEach = require('./_arrayEach'),
 2      arrayPush = require('./_arrayPush'),
 3      baseFunctions = require('./_baseFunctions'),
 4      copyArray = require('./_copyArray'),
 5      isFunction = require('./isFunction'),
 6      isObject = require('./isObject'),
 7      keys = require('./keys');
 8  
 9  /**
10   * Adds all own enumerable string keyed function properties of a source
11   * object to the destination object. If `object` is a function, then methods
12   * are added to its prototype as well.
13   *
14   * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15   * avoid conflicts caused by modifying the original.
16   *
17   * @static
18   * @since 0.1.0
19   * @memberOf _
20   * @category Util
21   * @param {Function|Object} [object=lodash] The destination object.
22   * @param {Object} source The object of functions to add.
23   * @param {Object} [options={}] The options object.
24   * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
25   * @returns {Function|Object} Returns `object`.
26   * @example
27   *
28   * function vowels(string) {
29   *   return _.filter(string, function(v) {
30   *     return /[aeiou]/i.test(v);
31   *   });
32   * }
33   *
34   * _.mixin({ 'vowels': vowels });
35   * _.vowels('fred');
36   * // => ['e']
37   *
38   * _('fred').vowels().value();
39   * // => ['e']
40   *
41   * _.mixin({ 'vowels': vowels }, { 'chain': false });
42   * _('fred').vowels();
43   * // => ['e']
44   */
45  function mixin(object, source, options) {
46    var props = keys(source),
47        methodNames = baseFunctions(source, props);
48  
49    var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
50        isFunc = isFunction(object);
51  
52    arrayEach(methodNames, function(methodName) {
53      var func = source[methodName];
54      object[methodName] = func;
55      if (isFunc) {
56        object.prototype[methodName] = function() {
57          var chainAll = this.__chain__;
58          if (chain || chainAll) {
59            var result = object(this.__wrapped__),
60                actions = result.__actions__ = copyArray(this.__actions__);
61  
62            actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
63            result.__chain__ = chainAll;
64            return result;
65          }
66          return func.apply(object, arrayPush([this.value()], arguments));
67        };
68      }
69    });
70  
71    return object;
72  }
73  
74  module.exports = mixin;