"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/underscore/underscore.js" (11 Apr 2017, 45489 Bytes) of package /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 //     Underscore.js 1.6.0
    2 //     http://underscorejs.org
    3 //     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
    4 //     Underscore may be freely distributed under the MIT license.
    5 
    6 (function() {
    7 
    8   // Baseline setup
    9   // --------------
   10 
   11   // Establish the root object, `window` in the browser, or `exports` on the server.
   12   var root = this;
   13 
   14   // Save the previous value of the `_` variable.
   15   var previousUnderscore = root._;
   16 
   17   // Establish the object that gets returned to break out of a loop iteration.
   18   var breaker = {};
   19 
   20   // Save bytes in the minified (but not gzipped) version:
   21   var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
   22 
   23   // Create quick reference variables for speed access to core prototypes.
   24   var
   25     push             = ArrayProto.push,
   26     slice            = ArrayProto.slice,
   27     concat           = ArrayProto.concat,
   28     toString         = ObjProto.toString,
   29     hasOwnProperty   = ObjProto.hasOwnProperty;
   30 
   31   // All **ECMAScript 5** native function implementations that we hope to use
   32   // are declared here.
   33   var
   34     nativeForEach      = ArrayProto.forEach,
   35     nativeMap          = ArrayProto.map,
   36     nativeReduce       = ArrayProto.reduce,
   37     nativeReduceRight  = ArrayProto.reduceRight,
   38     nativeFilter       = ArrayProto.filter,
   39     nativeEvery        = ArrayProto.every,
   40     nativeSome         = ArrayProto.some,
   41     nativeIndexOf      = ArrayProto.indexOf,
   42     nativeLastIndexOf  = ArrayProto.lastIndexOf,
   43     nativeIsArray      = Array.isArray,
   44     nativeKeys         = Object.keys,
   45     nativeBind         = FuncProto.bind;
   46 
   47   // Create a safe reference to the Underscore object for use below.
   48   var _ = function(obj) {
   49     if (obj instanceof _) return obj;
   50     if (!(this instanceof _)) return new _(obj);
   51     this._wrapped = obj;
   52   };
   53 
   54   // Export the Underscore object for **Node.js**, with
   55   // backwards-compatibility for the old `require()` API. If we're in
   56   // the browser, add `_` as a global object via a string identifier,
   57   // for Closure Compiler "advanced" mode.
   58   if (typeof exports !== 'undefined') {
   59     if (typeof module !== 'undefined' && module.exports) {
   60       exports = module.exports = _;
   61     }
   62     exports._ = _;
   63   } else {
   64     root._ = _;
   65   }
   66 
   67   // Current version.
   68   _.VERSION = '1.6.0';
   69 
   70   // Collection Functions
   71   // --------------------
   72 
   73   // The cornerstone, an `each` implementation, aka `forEach`.
   74   // Handles objects with the built-in `forEach`, arrays, and raw objects.
   75   // Delegates to **ECMAScript 5**'s native `forEach` if available.
   76   var each = _.each = _.forEach = function(obj, iterator, context) {
   77     if (obj == null) return obj;
   78     if (nativeForEach && obj.forEach === nativeForEach) {
   79       obj.forEach(iterator, context);
   80     } else if (obj.length === +obj.length) {
   81       for (var i = 0, length = obj.length; i < length; i++) {
   82         if (iterator.call(context, obj[i], i, obj) === breaker) return;
   83       }
   84     } else {
   85       var keys = _.keys(obj);
   86       for (var i = 0, length = keys.length; i < length; i++) {
   87         if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
   88       }
   89     }
   90     return obj;
   91   };
   92 
   93   // Return the results of applying the iterator to each element.
   94   // Delegates to **ECMAScript 5**'s native `map` if available.
   95   _.map = _.collect = function(obj, iterator, context) {
   96     var results = [];
   97     if (obj == null) return results;
   98     if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
   99     each(obj, function(value, index, list) {
  100       results.push(iterator.call(context, value, index, list));
  101     });
  102     return results;
  103   };
  104 
  105   var reduceError = 'Reduce of empty array with no initial value';
  106 
  107   // **Reduce** builds up a single result from a list of values, aka `inject`,
  108   // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
  109   _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
  110     var initial = arguments.length > 2;
  111     if (obj == null) obj = [];
  112     if (nativeReduce && obj.reduce === nativeReduce) {
  113       if (context) iterator = _.bind(iterator, context);
  114       return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
  115     }
  116     each(obj, function(value, index, list) {
  117       if (!initial) {
  118         memo = value;
  119         initial = true;
  120       } else {
  121         memo = iterator.call(context, memo, value, index, list);
  122       }
  123     });
  124     if (!initial) throw new TypeError(reduceError);
  125     return memo;
  126   };
  127 
  128   // The right-associative version of reduce, also known as `foldr`.
  129   // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
  130   _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
  131     var initial = arguments.length > 2;
  132     if (obj == null) obj = [];
  133     if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
  134       if (context) iterator = _.bind(iterator, context);
  135       return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
  136     }
  137     var length = obj.length;
  138     if (length !== +length) {
  139       var keys = _.keys(obj);
  140       length = keys.length;
  141     }
  142     each(obj, function(value, index, list) {
  143       index = keys ? keys[--length] : --length;
  144       if (!initial) {
  145         memo = obj[index];
  146         initial = true;
  147       } else {
  148         memo = iterator.call(context, memo, obj[index], index, list);
  149       }
  150     });
  151     if (!initial) throw new TypeError(reduceError);
  152     return memo;
  153   };
  154 
  155   // Return the first value which passes a truth test. Aliased as `detect`.
  156   _.find = _.detect = function(obj, predicate, context) {
  157     var result;
  158     any(obj, function(value, index, list) {
  159       if (predicate.call(context, value, index, list)) {
  160         result = value;
  161         return true;
  162       }
  163     });
  164     return result;
  165   };
  166 
  167   // Return all the elements that pass a truth test.
  168   // Delegates to **ECMAScript 5**'s native `filter` if available.
  169   // Aliased as `select`.
  170   _.filter = _.select = function(obj, predicate, context) {
  171     var results = [];
  172     if (obj == null) return results;
  173     if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
  174     each(obj, function(value, index, list) {
  175       if (predicate.call(context, value, index, list)) results.push(value);
  176     });
  177     return results;
  178   };
  179 
  180   // Return all the elements for which a truth test fails.
  181   _.reject = function(obj, predicate, context) {
  182     return _.filter(obj, function(value, index, list) {
  183       return !predicate.call(context, value, index, list);
  184     }, context);
  185   };
  186 
  187   // Determine whether all of the elements match a truth test.
  188   // Delegates to **ECMAScript 5**'s native `every` if available.
  189   // Aliased as `all`.
  190   _.every = _.all = function(obj, predicate, context) {
  191     predicate || (predicate = _.identity);
  192     var result = true;
  193     if (obj == null) return result;
  194     if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
  195     each(obj, function(value, index, list) {
  196       if (!(result = result && predicate.call(context, value, index, list))) return breaker;
  197     });
  198     return !!result;
  199   };
  200 
  201   // Determine if at least one element in the object matches a truth test.
  202   // Delegates to **ECMAScript 5**'s native `some` if available.
  203   // Aliased as `any`.
  204   var any = _.some = _.any = function(obj, predicate, context) {
  205     predicate || (predicate = _.identity);
  206     var result = false;
  207     if (obj == null) return result;
  208     if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
  209     each(obj, function(value, index, list) {
  210       if (result || (result = predicate.call(context, value, index, list))) return breaker;
  211     });
  212     return !!result;
  213   };
  214 
  215   // Determine if the array or object contains a given value (using `===`).
  216   // Aliased as `include`.
  217   _.contains = _.include = function(obj, target) {
  218     if (obj == null) return false;
  219     if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
  220     return any(obj, function(value) {
  221       return value === target;
  222     });
  223   };
  224 
  225   // Invoke a method (with arguments) on every item in a collection.
  226   _.invoke = function(obj, method) {
  227     var args = slice.call(arguments, 2);
  228     var isFunc = _.isFunction(method);
  229     return _.map(obj, function(value) {
  230       return (isFunc ? method : value[method]).apply(value, args);
  231     });
  232   };
  233 
  234   // Convenience version of a common use case of `map`: fetching a property.
  235   _.pluck = function(obj, key) {
  236     return _.map(obj, _.property(key));
  237   };
  238 
  239   // Convenience version of a common use case of `filter`: selecting only objects
  240   // containing specific `key:value` pairs.
  241   _.where = function(obj, attrs) {
  242     return _.filter(obj, _.matches(attrs));
  243   };
  244 
  245   // Convenience version of a common use case of `find`: getting the first object
  246   // containing specific `key:value` pairs.
  247   _.findWhere = function(obj, attrs) {
  248     return _.find(obj, _.matches(attrs));
  249   };
  250 
  251   // Return the maximum element or (element-based computation).
  252   // Can't optimize arrays of integers longer than 65,535 elements.
  253   // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
  254   _.max = function(obj, iterator, context) {
  255     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
  256       return Math.max.apply(Math, obj);
  257     }
  258     var result = -Infinity, lastComputed = -Infinity;
  259     each(obj, function(value, index, list) {
  260       var computed = iterator ? iterator.call(context, value, index, list) : value;
  261       if (computed > lastComputed) {
  262         result = value;
  263         lastComputed = computed;
  264       }
  265     });
  266     return result;
  267   };
  268 
  269   // Return the minimum element (or element-based computation).
  270   _.min = function(obj, iterator, context) {
  271     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
  272       return Math.min.apply(Math, obj);
  273     }
  274     var result = Infinity, lastComputed = Infinity;
  275     each(obj, function(value, index, list) {
  276       var computed = iterator ? iterator.call(context, value, index, list) : value;
  277       if (computed < lastComputed) {
  278         result = value;
  279         lastComputed = computed;
  280       }
  281     });
  282     return result;
  283   };
  284 
  285   // Shuffle an array, using the modern version of the
  286   // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
  287   _.shuffle = function(obj) {
  288     var rand;
  289     var index = 0;
  290     var shuffled = [];
  291     each(obj, function(value) {
  292       rand = _.random(index++);
  293       shuffled[index - 1] = shuffled[rand];
  294       shuffled[rand] = value;
  295     });
  296     return shuffled;
  297   };
  298 
  299   // Sample **n** random values from a collection.
  300   // If **n** is not specified, returns a single random element.
  301   // The internal `guard` argument allows it to work with `map`.
  302   _.sample = function(obj, n, guard) {
  303     if (n == null || guard) {
  304       if (obj.length !== +obj.length) obj = _.values(obj);
  305       return obj[_.random(obj.length - 1)];
  306     }
  307     return _.shuffle(obj).slice(0, Math.max(0, n));
  308   };
  309 
  310   // An internal function to generate lookup iterators.
  311   var lookupIterator = function(value) {
  312     if (value == null) return _.identity;
  313     if (_.isFunction(value)) return value;
  314     return _.property(value);
  315   };
  316 
  317   // Sort the object's values by a criterion produced by an iterator.
  318   _.sortBy = function(obj, iterator, context) {
  319     iterator = lookupIterator(iterator);
  320     return _.pluck(_.map(obj, function(value, index, list) {
  321       return {
  322         value: value,
  323         index: index,
  324         criteria: iterator.call(context, value, index, list)
  325       };
  326     }).sort(function(left, right) {
  327       var a = left.criteria;
  328       var b = right.criteria;
  329       if (a !== b) {
  330         if (a > b || a === void 0) return 1;
  331         if (a < b || b === void 0) return -1;
  332       }
  333       return left.index - right.index;
  334     }), 'value');
  335   };
  336 
  337   // An internal function used for aggregate "group by" operations.
  338   var group = function(behavior) {
  339     return function(obj, iterator, context) {
  340       var result = {};
  341       iterator = lookupIterator(iterator);
  342       each(obj, function(value, index) {
  343         var key = iterator.call(context, value, index, obj);
  344         behavior(result, key, value);
  345       });
  346       return result;
  347     };
  348   };
  349 
  350   // Groups the object's values by a criterion. Pass either a string attribute
  351   // to group by, or a function that returns the criterion.
  352   _.groupBy = group(function(result, key, value) {
  353     _.has(result, key) ? result[key].push(value) : result[key] = [value];
  354   });
  355 
  356   // Indexes the object's values by a criterion, similar to `groupBy`, but for
  357   // when you know that your index values will be unique.
  358   _.indexBy = group(function(result, key, value) {
  359     result[key] = value;
  360   });
  361 
  362   // Counts instances of an object that group by a certain criterion. Pass
  363   // either a string attribute to count by, or a function that returns the
  364   // criterion.
  365   _.countBy = group(function(result, key) {
  366     _.has(result, key) ? result[key]++ : result[key] = 1;
  367   });
  368 
  369   // Use a comparator function to figure out the smallest index at which
  370   // an object should be inserted so as to maintain order. Uses binary search.
  371   _.sortedIndex = function(array, obj, iterator, context) {
  372     iterator = lookupIterator(iterator);
  373     var value = iterator.call(context, obj);
  374     var low = 0, high = array.length;
  375     while (low < high) {
  376       var mid = (low + high) >>> 1;
  377       iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
  378     }
  379     return low;
  380   };
  381 
  382   // Safely create a real, live array from anything iterable.
  383   _.toArray = function(obj) {
  384     if (!obj) return [];
  385     if (_.isArray(obj)) return slice.call(obj);
  386     if (obj.length === +obj.length) return _.map(obj, _.identity);
  387     return _.values(obj);
  388   };
  389 
  390   // Return the number of elements in an object.
  391   _.size = function(obj) {
  392     if (obj == null) return 0;
  393     return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
  394   };
  395 
  396   // Array Functions
  397   // ---------------
  398 
  399   // Get the first element of an array. Passing **n** will return the first N
  400   // values in the array. Aliased as `head` and `take`. The **guard** check
  401   // allows it to work with `_.map`.
  402   _.first = _.head = _.take = function(array, n, guard) {
  403     if (array == null) return void 0;
  404     if ((n == null) || guard) return array[0];
  405     if (n < 0) return [];
  406     return slice.call(array, 0, n);
  407   };
  408 
  409   // Returns everything but the last entry of the array. Especially useful on
  410   // the arguments object. Passing **n** will return all the values in
  411   // the array, excluding the last N. The **guard** check allows it to work with
  412   // `_.map`.
  413   _.initial = function(array, n, guard) {
  414     return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
  415   };
  416 
  417   // Get the last element of an array. Passing **n** will return the last N
  418   // values in the array. The **guard** check allows it to work with `_.map`.
  419   _.last = function(array, n, guard) {
  420     if (array == null) return void 0;
  421     if ((n == null) || guard) return array[array.length - 1];
  422     return slice.call(array, Math.max(array.length - n, 0));
  423   };
  424 
  425   // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
  426   // Especially useful on the arguments object. Passing an **n** will return
  427   // the rest N values in the array. The **guard**
  428   // check allows it to work with `_.map`.
  429   _.rest = _.tail = _.drop = function(array, n, guard) {
  430     return slice.call(array, (n == null) || guard ? 1 : n);
  431   };
  432 
  433   // Trim out all falsy values from an array.
  434   _.compact = function(array) {
  435     return _.filter(array, _.identity);
  436   };
  437 
  438   // Internal implementation of a recursive `flatten` function.
  439   var flatten = function(input, shallow, output) {
  440     if (shallow && _.every(input, _.isArray)) {
  441       return concat.apply(output, input);
  442     }
  443     each(input, function(value) {
  444       if (_.isArray(value) || _.isArguments(value)) {
  445         shallow ? push.apply(output, value) : flatten(value, shallow, output);
  446       } else {
  447         output.push(value);
  448       }
  449     });
  450     return output;
  451   };
  452 
  453   // Flatten out an array, either recursively (by default), or just one level.
  454   _.flatten = function(array, shallow) {
  455     return flatten(array, shallow, []);
  456   };
  457 
  458   // Return a version of the array that does not contain the specified value(s).
  459   _.without = function(array) {
  460     return _.difference(array, slice.call(arguments, 1));
  461   };
  462 
  463   // Split an array into two arrays: one whose elements all satisfy the given
  464   // predicate, and one whose elements all do not satisfy the predicate.
  465   _.partition = function(array, predicate) {
  466     var pass = [], fail = [];
  467     each(array, function(elem) {
  468       (predicate(elem) ? pass : fail).push(elem);
  469     });
  470     return [pass, fail];
  471   };
  472 
  473   // Produce a duplicate-free version of the array. If the array has already
  474   // been sorted, you have the option of using a faster algorithm.
  475   // Aliased as `unique`.
  476   _.uniq = _.unique = function(array, isSorted, iterator, context) {
  477     if (_.isFunction(isSorted)) {
  478       context = iterator;
  479       iterator = isSorted;
  480       isSorted = false;
  481     }
  482     var initial = iterator ? _.map(array, iterator, context) : array;
  483     var results = [];
  484     var seen = [];
  485     each(initial, function(value, index) {
  486       if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
  487         seen.push(value);
  488         results.push(array[index]);
  489       }
  490     });
  491     return results;
  492   };
  493 
  494   // Produce an array that contains the union: each distinct element from all of
  495   // the passed-in arrays.
  496   _.union = function() {
  497     return _.uniq(_.flatten(arguments, true));
  498   };
  499 
  500   // Produce an array that contains every item shared between all the
  501   // passed-in arrays.
  502   _.intersection = function(array) {
  503     var rest = slice.call(arguments, 1);
  504     return _.filter(_.uniq(array), function(item) {
  505       return _.every(rest, function(other) {
  506         return _.contains(other, item);
  507       });
  508     });
  509   };
  510 
  511   // Take the difference between one array and a number of other arrays.
  512   // Only the elements present in just the first array will remain.
  513   _.difference = function(array) {
  514     var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
  515     return _.filter(array, function(value){ return !_.contains(rest, value); });
  516   };
  517 
  518   // Zip together multiple lists into a single array -- elements that share
  519   // an index go together.
  520   _.zip = function() {
  521     var length = _.max(_.pluck(arguments, 'length').concat(0));
  522     var results = new Array(length);
  523     for (var i = 0; i < length; i++) {
  524       results[i] = _.pluck(arguments, '' + i);
  525     }
  526     return results;
  527   };
  528 
  529   // Converts lists into objects. Pass either a single array of `[key, value]`
  530   // pairs, or two parallel arrays of the same length -- one of keys, and one of
  531   // the corresponding values.
  532   _.object = function(list, values) {
  533     if (list == null) return {};
  534     var result = {};
  535     for (var i = 0, length = list.length; i < length; i++) {
  536       if (values) {
  537         result[list[i]] = values[i];
  538       } else {
  539         result[list[i][0]] = list[i][1];
  540       }
  541     }
  542     return result;
  543   };
  544 
  545   // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
  546   // we need this function. Return the position of the first occurrence of an
  547   // item in an array, or -1 if the item is not included in the array.
  548   // Delegates to **ECMAScript 5**'s native `indexOf` if available.
  549   // If the array is large and already in sort order, pass `true`
  550   // for **isSorted** to use binary search.
  551   _.indexOf = function(array, item, isSorted) {
  552     if (array == null) return -1;
  553     var i = 0, length = array.length;
  554     if (isSorted) {
  555       if (typeof isSorted == 'number') {
  556         i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
  557       } else {
  558         i = _.sortedIndex(array, item);
  559         return array[i] === item ? i : -1;
  560       }
  561     }
  562     if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
  563     for (; i < length; i++) if (array[i] === item) return i;
  564     return -1;
  565   };
  566 
  567   // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
  568   _.lastIndexOf = function(array, item, from) {
  569     if (array == null) return -1;
  570     var hasIndex = from != null;
  571     if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
  572       return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
  573     }
  574     var i = (hasIndex ? from : array.length);
  575     while (i--) if (array[i] === item) return i;
  576     return -1;
  577   };
  578 
  579   // Generate an integer Array containing an arithmetic progression. A port of
  580   // the native Python `range()` function. See
  581   // [the Python documentation](http://docs.python.org/library/functions.html#range).
  582   _.range = function(start, stop, step) {
  583     if (arguments.length <= 1) {
  584       stop = start || 0;
  585       start = 0;
  586     }
  587     step = arguments[2] || 1;
  588 
  589     var length = Math.max(Math.ceil((stop - start) / step), 0);
  590     var idx = 0;
  591     var range = new Array(length);
  592 
  593     while(idx < length) {
  594       range[idx++] = start;
  595       start += step;
  596     }
  597 
  598     return range;
  599   };
  600 
  601   // Function (ahem) Functions
  602   // ------------------
  603 
  604   // Reusable constructor function for prototype setting.
  605   var ctor = function(){};
  606 
  607   // Create a function bound to a given object (assigning `this`, and arguments,
  608   // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
  609   // available.
  610   _.bind = function(func, context) {
  611     var args, bound;
  612     if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
  613     if (!_.isFunction(func)) throw new TypeError;
  614     args = slice.call(arguments, 2);
  615     return bound = function() {
  616       if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
  617       ctor.prototype = func.prototype;
  618       var self = new ctor;
  619       ctor.prototype = null;
  620       var result = func.apply(self, args.concat(slice.call(arguments)));
  621       if (Object(result) === result) return result;
  622       return self;
  623     };
  624   };
  625 
  626   // Partially apply a function by creating a version that has had some of its
  627   // arguments pre-filled, without changing its dynamic `this` context. _ acts
  628   // as a placeholder, allowing any combination of arguments to be pre-filled.
  629   _.partial = function(func) {
  630     var boundArgs = slice.call(arguments, 1);
  631     return function() {
  632       var position = 0;
  633       var args = boundArgs.slice();
  634       for (var i = 0, length = args.length; i < length; i++) {
  635         if (args[i] === _) args[i] = arguments[position++];
  636       }
  637       while (position < arguments.length) args.push(arguments[position++]);
  638       return func.apply(this, args);
  639     };
  640   };
  641 
  642   // Bind a number of an object's methods to that object. Remaining arguments
  643   // are the method names to be bound. Useful for ensuring that all callbacks
  644   // defined on an object belong to it.
  645   _.bindAll = function(obj) {
  646     var funcs = slice.call(arguments, 1);
  647     if (funcs.length === 0) throw new Error('bindAll must be passed function names');
  648     each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
  649     return obj;
  650   };
  651 
  652   // Memoize an expensive function by storing its results.
  653   _.memoize = function(func, hasher) {
  654     var memo = {};
  655     hasher || (hasher = _.identity);
  656     return function() {
  657       var key = hasher.apply(this, arguments);
  658       return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
  659     };
  660   };
  661 
  662   // Delays a function for the given number of milliseconds, and then calls
  663   // it with the arguments supplied.
  664   _.delay = function(func, wait) {
  665     var args = slice.call(arguments, 2);
  666     return setTimeout(function(){ return func.apply(null, args); }, wait);
  667   };
  668 
  669   // Defers a function, scheduling it to run after the current call stack has
  670   // cleared.
  671   _.defer = function(func) {
  672     return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  673   };
  674 
  675   // Returns a function, that, when invoked, will only be triggered at most once
  676   // during a given window of time. Normally, the throttled function will run
  677   // as much as it can, without ever going more than once per `wait` duration;
  678   // but if you'd like to disable the execution on the leading edge, pass
  679   // `{leading: false}`. To disable execution on the trailing edge, ditto.
  680   _.throttle = function(func, wait, options) {
  681     var context, args, result;
  682     var timeout = null;
  683     var previous = 0;
  684     options || (options = {});
  685     var later = function() {
  686       previous = options.leading === false ? 0 : _.now();
  687       timeout = null;
  688       result = func.apply(context, args);
  689       context = args = null;
  690     };
  691     return function() {
  692       var now = _.now();
  693       if (!previous && options.leading === false) previous = now;
  694       var remaining = wait - (now - previous);
  695       context = this;
  696       args = arguments;
  697       if (remaining <= 0) {
  698         clearTimeout(timeout);
  699         timeout = null;
  700         previous = now;
  701         result = func.apply(context, args);
  702         context = args = null;
  703       } else if (!timeout && options.trailing !== false) {
  704         timeout = setTimeout(later, remaining);
  705       }
  706       return result;
  707     };
  708   };
  709 
  710   // Returns a function, that, as long as it continues to be invoked, will not
  711   // be triggered. The function will be called after it stops being called for
  712   // N milliseconds. If `immediate` is passed, trigger the function on the
  713   // leading edge, instead of the trailing.
  714   _.debounce = function(func, wait, immediate) {
  715     var timeout, args, context, timestamp, result;
  716 
  717     var later = function() {
  718       var last = _.now() - timestamp;
  719       if (last < wait) {
  720         timeout = setTimeout(later, wait - last);
  721       } else {
  722         timeout = null;
  723         if (!immediate) {
  724           result = func.apply(context, args);
  725           context = args = null;
  726         }
  727       }
  728     };
  729 
  730     return function() {
  731       context = this;
  732       args = arguments;
  733       timestamp = _.now();
  734       var callNow = immediate && !timeout;
  735       if (!timeout) {
  736         timeout = setTimeout(later, wait);
  737       }
  738       if (callNow) {
  739         result = func.apply(context, args);
  740         context = args = null;
  741       }
  742 
  743       return result;
  744     };
  745   };
  746 
  747   // Returns a function that will be executed at most one time, no matter how
  748   // often you call it. Useful for lazy initialization.
  749   _.once = function(func) {
  750     var ran = false, memo;
  751     return function() {
  752       if (ran) return memo;
  753       ran = true;
  754       memo = func.apply(this, arguments);
  755       func = null;
  756       return memo;
  757     };
  758   };
  759 
  760   // Returns the first function passed as an argument to the second,
  761   // allowing you to adjust arguments, run code before and after, and
  762   // conditionally execute the original function.
  763   _.wrap = function(func, wrapper) {
  764     return _.partial(wrapper, func);
  765   };
  766 
  767   // Returns a function that is the composition of a list of functions, each
  768   // consuming the return value of the function that follows.
  769   _.compose = function() {
  770     var funcs = arguments;
  771     return function() {
  772       var args = arguments;
  773       for (var i = funcs.length - 1; i >= 0; i--) {
  774         args = [funcs[i].apply(this, args)];
  775       }
  776       return args[0];
  777     };
  778   };
  779 
  780   // Returns a function that will only be executed after being called N times.
  781   _.after = function(times, func) {
  782     return function() {
  783       if (--times < 1) {
  784         return func.apply(this, arguments);
  785       }
  786     };
  787   };
  788 
  789   // Object Functions
  790   // ----------------
  791 
  792   // Retrieve the names of an object's properties.
  793   // Delegates to **ECMAScript 5**'s native `Object.keys`
  794   _.keys = function(obj) {
  795     if (!_.isObject(obj)) return [];
  796     if (nativeKeys) return nativeKeys(obj);
  797     var keys = [];
  798     for (var key in obj) if (_.has(obj, key)) keys.push(key);
  799     return keys;
  800   };
  801 
  802   // Retrieve the values of an object's properties.
  803   _.values = function(obj) {
  804     var keys = _.keys(obj);
  805     var length = keys.length;
  806     var values = new Array(length);
  807     for (var i = 0; i < length; i++) {
  808       values[i] = obj[keys[i]];
  809     }
  810     return values;
  811   };
  812 
  813   // Convert an object into a list of `[key, value]` pairs.
  814   _.pairs = function(obj) {
  815     var keys = _.keys(obj);
  816     var length = keys.length;
  817     var pairs = new Array(length);
  818     for (var i = 0; i < length; i++) {
  819       pairs[i] = [keys[i], obj[keys[i]]];
  820     }
  821     return pairs;
  822   };
  823 
  824   // Invert the keys and values of an object. The values must be serializable.
  825   _.invert = function(obj) {
  826     var result = {};
  827     var keys = _.keys(obj);
  828     for (var i = 0, length = keys.length; i < length; i++) {
  829       result[obj[keys[i]]] = keys[i];
  830     }
  831     return result;
  832   };
  833 
  834   // Return a sorted list of the function names available on the object.
  835   // Aliased as `methods`
  836   _.functions = _.methods = function(obj) {
  837     var names = [];
  838     for (var key in obj) {
  839       if (_.isFunction(obj[key])) names.push(key);
  840     }
  841     return names.sort();
  842   };
  843 
  844   // Extend a given object with all the properties in passed-in object(s).
  845   _.extend = function(obj) {
  846     each(slice.call(arguments, 1), function(source) {
  847       if (source) {
  848         for (var prop in source) {
  849           obj[prop] = source[prop];
  850         }
  851       }
  852     });
  853     return obj;
  854   };
  855 
  856   // Return a copy of the object only containing the whitelisted properties.
  857   _.pick = function(obj) {
  858     var copy = {};
  859     var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
  860     each(keys, function(key) {
  861       if (key in obj) copy[key] = obj[key];
  862     });
  863     return copy;
  864   };
  865 
  866    // Return a copy of the object without the blacklisted properties.
  867   _.omit = function(obj) {
  868     var copy = {};
  869     var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
  870     for (var key in obj) {
  871       if (!_.contains(keys, key)) copy[key] = obj[key];
  872     }
  873     return copy;
  874   };
  875 
  876   // Fill in a given object with default properties.
  877   _.defaults = function(obj) {
  878     each(slice.call(arguments, 1), function(source) {
  879       if (source) {
  880         for (var prop in source) {
  881           if (obj[prop] === void 0) obj[prop] = source[prop];
  882         }
  883       }
  884     });
  885     return obj;
  886   };
  887 
  888   // Create a (shallow-cloned) duplicate of an object.
  889   _.clone = function(obj) {
  890     if (!_.isObject(obj)) return obj;
  891     return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  892   };
  893 
  894   // Invokes interceptor with the obj, and then returns obj.
  895   // The primary purpose of this method is to "tap into" a method chain, in
  896   // order to perform operations on intermediate results within the chain.
  897   _.tap = function(obj, interceptor) {
  898     interceptor(obj);
  899     return obj;
  900   };
  901 
  902   // Internal recursive comparison function for `isEqual`.
  903   var eq = function(a, b, aStack, bStack) {
  904     // Identical objects are equal. `0 === -0`, but they aren't identical.
  905     // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
  906     if (a === b) return a !== 0 || 1 / a == 1 / b;
  907     // A strict comparison is necessary because `null == undefined`.
  908     if (a == null || b == null) return a === b;
  909     // Unwrap any wrapped objects.
  910     if (a instanceof _) a = a._wrapped;
  911     if (b instanceof _) b = b._wrapped;
  912     // Compare `[[Class]]` names.
  913     var className = toString.call(a);
  914     if (className != toString.call(b)) return false;
  915     switch (className) {
  916       // Strings, numbers, dates, and booleans are compared by value.
  917       case '[object String]':
  918         // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
  919         // equivalent to `new String("5")`.
  920         return a == String(b);
  921       case '[object Number]':
  922         // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
  923         // other numeric values.
  924         return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
  925       case '[object Date]':
  926       case '[object Boolean]':
  927         // Coerce dates and booleans to numeric primitive values. Dates are compared by their
  928         // millisecond representations. Note that invalid dates with millisecond representations
  929         // of `NaN` are not equivalent.
  930         return +a == +b;
  931       // RegExps are compared by their source patterns and flags.
  932       case '[object RegExp]':
  933         return a.source == b.source &&
  934                a.global == b.global &&
  935                a.multiline == b.multiline &&
  936                a.ignoreCase == b.ignoreCase;
  937     }
  938     if (typeof a != 'object' || typeof b != 'object') return false;
  939     // Assume equality for cyclic structures. The algorithm for detecting cyclic
  940     // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  941     var length = aStack.length;
  942     while (length--) {
  943       // Linear search. Performance is inversely proportional to the number of
  944       // unique nested structures.
  945       if (aStack[length] == a) return bStack[length] == b;
  946     }
  947     // Objects with different constructors are not equivalent, but `Object`s
  948     // from different frames are.
  949     var aCtor = a.constructor, bCtor = b.constructor;
  950     if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
  951                              _.isFunction(bCtor) && (bCtor instanceof bCtor))
  952                         && ('constructor' in a && 'constructor' in b)) {
  953       return false;
  954     }
  955     // Add the first object to the stack of traversed objects.
  956     aStack.push(a);
  957     bStack.push(b);
  958     var size = 0, result = true;
  959     // Recursively compare objects and arrays.
  960     if (className == '[object Array]') {
  961       // Compare array lengths to determine if a deep comparison is necessary.
  962       size = a.length;
  963       result = size == b.length;
  964       if (result) {
  965         // Deep compare the contents, ignoring non-numeric properties.
  966         while (size--) {
  967           if (!(result = eq(a[size], b[size], aStack, bStack))) break;
  968         }
  969       }
  970     } else {
  971       // Deep compare objects.
  972       for (var key in a) {
  973         if (_.has(a, key)) {
  974           // Count the expected number of properties.
  975           size++;
  976           // Deep compare each member.
  977           if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
  978         }
  979       }
  980       // Ensure that both objects contain the same number of properties.
  981       if (result) {
  982         for (key in b) {
  983           if (_.has(b, key) && !(size--)) break;
  984         }
  985         result = !size;
  986       }
  987     }
  988     // Remove the first object from the stack of traversed objects.
  989     aStack.pop();
  990     bStack.pop();
  991     return result;
  992   };
  993 
  994   // Perform a deep comparison to check if two objects are equal.
  995   _.isEqual = function(a, b) {
  996     return eq(a, b, [], []);
  997   };
  998 
  999   // Is a given array, string, or object empty?
 1000   // An "empty" object has no enumerable own-properties.
 1001   _.isEmpty = function(obj) {
 1002     if (obj == null) return true;
 1003     if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
 1004     for (var key in obj) if (_.has(obj, key)) return false;
 1005     return true;
 1006   };
 1007 
 1008   // Is a given value a DOM element?
 1009   _.isElement = function(obj) {
 1010     return !!(obj && obj.nodeType === 1);
 1011   };
 1012 
 1013   // Is a given value an array?
 1014   // Delegates to ECMA5's native Array.isArray
 1015   _.isArray = nativeIsArray || function(obj) {
 1016     return toString.call(obj) == '[object Array]';
 1017   };
 1018 
 1019   // Is a given variable an object?
 1020   _.isObject = function(obj) {
 1021     return obj === Object(obj);
 1022   };
 1023 
 1024   // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
 1025   each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
 1026     _['is' + name] = function(obj) {
 1027       return toString.call(obj) == '[object ' + name + ']';
 1028     };
 1029   });
 1030 
 1031   // Define a fallback version of the method in browsers (ahem, IE), where
 1032   // there isn't any inspectable "Arguments" type.
 1033   if (!_.isArguments(arguments)) {
 1034     _.isArguments = function(obj) {
 1035       return !!(obj && _.has(obj, 'callee'));
 1036     };
 1037   }
 1038 
 1039   // Optimize `isFunction` if appropriate.
 1040   if (typeof (/./) !== 'function') {
 1041     _.isFunction = function(obj) {
 1042       return typeof obj === 'function';
 1043     };
 1044   }
 1045 
 1046   // Is a given object a finite number?
 1047   _.isFinite = function(obj) {
 1048     return isFinite(obj) && !isNaN(parseFloat(obj));
 1049   };
 1050 
 1051   // Is the given value `NaN`? (NaN is the only number which does not equal itself).
 1052   _.isNaN = function(obj) {
 1053     return _.isNumber(obj) && obj != +obj;
 1054   };
 1055 
 1056   // Is a given value a boolean?
 1057   _.isBoolean = function(obj) {
 1058     return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
 1059   };
 1060 
 1061   // Is a given value equal to null?
 1062   _.isNull = function(obj) {
 1063     return obj === null;
 1064   };
 1065 
 1066   // Is a given variable undefined?
 1067   _.isUndefined = function(obj) {
 1068     return obj === void 0;
 1069   };
 1070 
 1071   // Shortcut function for checking if an object has a given property directly
 1072   // on itself (in other words, not on a prototype).
 1073   _.has = function(obj, key) {
 1074     return hasOwnProperty.call(obj, key);
 1075   };
 1076 
 1077   // Utility Functions
 1078   // -----------------
 1079 
 1080   // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
 1081   // previous owner. Returns a reference to the Underscore object.
 1082   _.noConflict = function() {
 1083     root._ = previousUnderscore;
 1084     return this;
 1085   };
 1086 
 1087   // Keep the identity function around for default iterators.
 1088   _.identity = function(value) {
 1089     return value;
 1090   };
 1091 
 1092   _.constant = function(value) {
 1093     return function () {
 1094       return value;
 1095     };
 1096   };
 1097 
 1098   _.property = function(key) {
 1099     return function(obj) {
 1100       return obj[key];
 1101     };
 1102   };
 1103 
 1104   // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
 1105   _.matches = function(attrs) {
 1106     return function(obj) {
 1107       if (obj === attrs) return true; //avoid comparing an object to itself.
 1108       for (var key in attrs) {
 1109         if (attrs[key] !== obj[key])
 1110           return false;
 1111       }
 1112       return true;
 1113     }
 1114   };
 1115 
 1116   // Run a function **n** times.
 1117   _.times = function(n, iterator, context) {
 1118     var accum = Array(Math.max(0, n));
 1119     for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
 1120     return accum;
 1121   };
 1122 
 1123   // Return a random integer between min and max (inclusive).
 1124   _.random = function(min, max) {
 1125     if (max == null) {
 1126       max = min;
 1127       min = 0;
 1128     }
 1129     return min + Math.floor(Math.random() * (max - min + 1));
 1130   };
 1131 
 1132   // A (possibly faster) way to get the current timestamp as an integer.
 1133   _.now = Date.now || function() { return new Date().getTime(); };
 1134 
 1135   // List of HTML entities for escaping.
 1136   var entityMap = {
 1137     escape: {
 1138       '&': '&amp;',
 1139       '<': '&lt;',
 1140       '>': '&gt;',
 1141       '"': '&quot;',
 1142       "'": '&#x27;'
 1143     }
 1144   };
 1145   entityMap.unescape = _.invert(entityMap.escape);
 1146 
 1147   // Regexes containing the keys and values listed immediately above.
 1148   var entityRegexes = {
 1149     escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
 1150     unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
 1151   };
 1152 
 1153   // Functions for escaping and unescaping strings to/from HTML interpolation.
 1154   _.each(['escape', 'unescape'], function(method) {
 1155     _[method] = function(string) {
 1156       if (string == null) return '';
 1157       return ('' + string).replace(entityRegexes[method], function(match) {
 1158         return entityMap[method][match];
 1159       });
 1160     };
 1161   });
 1162 
 1163   // If the value of the named `property` is a function then invoke it with the
 1164   // `object` as context; otherwise, return it.
 1165   _.result = function(object, property) {
 1166     if (object == null) return void 0;
 1167     var value = object[property];
 1168     return _.isFunction(value) ? value.call(object) : value;
 1169   };
 1170 
 1171   // Add your own custom functions to the Underscore object.
 1172   _.mixin = function(obj) {
 1173     each(_.functions(obj), function(name) {
 1174       var func = _[name] = obj[name];
 1175       _.prototype[name] = function() {
 1176         var args = [this._wrapped];
 1177         push.apply(args, arguments);
 1178         return result.call(this, func.apply(_, args));
 1179       };
 1180     });
 1181   };
 1182 
 1183   // Generate a unique integer id (unique within the entire client session).
 1184   // Useful for temporary DOM ids.
 1185   var idCounter = 0;
 1186   _.uniqueId = function(prefix) {
 1187     var id = ++idCounter + '';
 1188     return prefix ? prefix + id : id;
 1189   };
 1190 
 1191   // By default, Underscore uses ERB-style template delimiters, change the
 1192   // following template settings to use alternative delimiters.
 1193   _.templateSettings = {
 1194     evaluate    : /<%([\s\S]+?)%>/g,
 1195     interpolate : /<%=([\s\S]+?)%>/g,
 1196     escape      : /<%-([\s\S]+?)%>/g
 1197   };
 1198 
 1199   // When customizing `templateSettings`, if you don't want to define an
 1200   // interpolation, evaluation or escaping regex, we need one that is
 1201   // guaranteed not to match.
 1202   var noMatch = /(.)^/;
 1203 
 1204   // Certain characters need to be escaped so that they can be put into a
 1205   // string literal.
 1206   var escapes = {
 1207     "'":      "'",
 1208     '\\':     '\\',
 1209     '\r':     'r',
 1210     '\n':     'n',
 1211     '\t':     't',
 1212     '\u2028': 'u2028',
 1213     '\u2029': 'u2029'
 1214   };
 1215 
 1216   var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
 1217 
 1218   // JavaScript micro-templating, similar to John Resig's implementation.
 1219   // Underscore templating handles arbitrary delimiters, preserves whitespace,
 1220   // and correctly escapes quotes within interpolated code.
 1221   _.template = function(text, data, settings) {
 1222     var render;
 1223     settings = _.defaults({}, settings, _.templateSettings);
 1224 
 1225     // Combine delimiters into one regular expression via alternation.
 1226     var matcher = new RegExp([
 1227       (settings.escape || noMatch).source,
 1228       (settings.interpolate || noMatch).source,
 1229       (settings.evaluate || noMatch).source
 1230     ].join('|') + '|$', 'g');
 1231 
 1232     // Compile the template source, escaping string literals appropriately.
 1233     var index = 0;
 1234     var source = "__p+='";
 1235     text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
 1236       source += text.slice(index, offset)
 1237         .replace(escaper, function(match) { return '\\' + escapes[match]; });
 1238 
 1239       if (escape) {
 1240         source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
 1241       }
 1242       if (interpolate) {
 1243         source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
 1244       }
 1245       if (evaluate) {
 1246         source += "';\n" + evaluate + "\n__p+='";
 1247       }
 1248       index = offset + match.length;
 1249       return match;
 1250     });
 1251     source += "';\n";
 1252 
 1253     // If a variable is not specified, place data values in local scope.
 1254     if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
 1255 
 1256     source = "var __t,__p='',__j=Array.prototype.join," +
 1257       "print=function(){__p+=__j.call(arguments,'');};\n" +
 1258       source + "return __p;\n";
 1259 
 1260     try {
 1261       render = new Function(settings.variable || 'obj', '_', source);
 1262     } catch (e) {
 1263       e.source = source;
 1264       throw e;
 1265     }
 1266 
 1267     if (data) return render(data, _);
 1268     var template = function(data) {
 1269       return render.call(this, data, _);
 1270     };
 1271 
 1272     // Provide the compiled function source as a convenience for precompilation.
 1273     template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
 1274 
 1275     return template;
 1276   };
 1277 
 1278   // Add a "chain" function, which will delegate to the wrapper.
 1279   _.chain = function(obj) {
 1280     return _(obj).chain();
 1281   };
 1282 
 1283   // OOP
 1284   // ---------------
 1285   // If Underscore is called as a function, it returns a wrapped object that
 1286   // can be used OO-style. This wrapper holds altered versions of all the
 1287   // underscore functions. Wrapped objects may be chained.
 1288 
 1289   // Helper function to continue chaining intermediate results.
 1290   var result = function(obj) {
 1291     return this._chain ? _(obj).chain() : obj;
 1292   };
 1293 
 1294   // Add all of the Underscore functions to the wrapper object.
 1295   _.mixin(_);
 1296 
 1297   // Add all mutator Array functions to the wrapper.
 1298   each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
 1299     var method = ArrayProto[name];
 1300     _.prototype[name] = function() {
 1301       var obj = this._wrapped;
 1302       method.apply(obj, arguments);
 1303       if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
 1304       return result.call(this, obj);
 1305     };
 1306   });
 1307 
 1308   // Add all accessor Array functions to the wrapper.
 1309   each(['concat', 'join', 'slice'], function(name) {
 1310     var method = ArrayProto[name];
 1311     _.prototype[name] = function() {
 1312       return result.call(this, method.apply(this._wrapped, arguments));
 1313     };
 1314   });
 1315 
 1316   _.extend(_.prototype, {
 1317 
 1318     // Start chaining a wrapped Underscore object.
 1319     chain: function() {
 1320       this._chain = true;
 1321       return this;
 1322     },
 1323 
 1324     // Extracts the result from a wrapped and chained object.
 1325     value: function() {
 1326       return this._wrapped;
 1327     }
 1328 
 1329   });
 1330 
 1331   // AMD registration happens at the end for compatibility with AMD loaders
 1332   // that may not enforce next-turn semantics on modules. Even though general
 1333   // practice for AMD registration is to be anonymous, underscore registers
 1334   // as a named module because, like jQuery, it is a base library that is
 1335   // popular enough to be bundled in a third party lib, but not be part of
 1336   // an AMD load request. Those cases could generate an error when an
 1337   // anonymous define() is called outside of a loader request.
 1338   if (typeof define === 'function' && define.amd) {
 1339     define('underscore', [], function() {
 1340       return _;
 1341     });
 1342   }
 1343 }).call(this);