diff --git a/bower.json b/bower.json index 12dbcdee2..6c6bbdab2 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "underscore", - "version": "1.5.2", + "version": "1.6.0", "main": "underscore.js", "keywords": ["util", "functional", "server", "client", "browser"], "ignore" : ["underscore-min.js", "docs", "test", "*.yml", "*.map", diff --git a/component.json b/component.json index 2b9d85e00..bb1775e70 100644 --- a/component.json +++ b/component.json @@ -5,6 +5,6 @@ "repo" : "jashkenas/underscore", "main" : "underscore.js", "scripts" : ["underscore.js"], - "version" : "1.5.2", + "version" : "1.6.0", "license" : "MIT" } diff --git a/docs/docco.css b/docs/docco.css index f690a0794..a2899ac87 100644 --- a/docs/docco.css +++ b/docs/docco.css @@ -51,9 +51,17 @@ b, strong { font-family: "aller-bold"; } -p, ul, ol { +p { margin: 15px 0 0px; } + .annotation ul, .annotation ol { + margin: 25px 0; + } + .annotation ul li, .annotation ol li { + font-size: 14px; + line-height: 18px; + margin: 10px 0; + } h1, h2, h3, h4, h5, h6 { color: #112233; @@ -70,7 +78,7 @@ h1 { hr { border: 0; - background: 1px solid #ddd; + background: 1px #ddd; height: 1px; margin: 20px 0; } @@ -205,7 +213,6 @@ ul.sections > li > div { } ul.sections > li > div.content { - background: #f5f5ff; overflow-x:auto; -webkit-box-shadow: inset 0 0 5px #e5e5ee; box-shadow: inset 0 0 5px #e5e5ee; @@ -306,7 +313,6 @@ ul.sections > li > div { ul.sections > li > div.content { padding: 13px; vertical-align: top; - background: #f5f5ff; border: none; -webkit-box-shadow: none; box-shadow: none; @@ -376,125 +382,125 @@ pre code { background: #f8f8ff } -pre .comment, -pre .template_comment, -pre .diff .header, -pre .javadoc { +pre .hljs-comment, +pre .hljs-template_comment, +pre .hljs-diff .hljs-header, +pre .hljs-javadoc { color: #408080; font-style: italic } -pre .keyword, -pre .assignment, -pre .literal, -pre .css .rule .keyword, -pre .winutils, -pre .javascript .title, -pre .lisp .title, -pre .subst { +pre .hljs-keyword, +pre .hljs-assignment, +pre .hljs-literal, +pre .hljs-css .hljs-rule .hljs-keyword, +pre .hljs-winutils, +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { color: #954121; /*font-weight: bold*/ } -pre .number, -pre .hexcolor { +pre .hljs-number, +pre .hljs-hexcolor { color: #40a070 } -pre .string, -pre .tag .value, -pre .phpdoc, -pre .tex .formula { +pre .hljs-string, +pre .hljs-tag .hljs-value, +pre .hljs-phpdoc, +pre .hljs-tex .hljs-formula { color: #219161; } -pre .title, -pre .id { +pre .hljs-title, +pre .hljs-id { color: #19469D; } -pre .params { +pre .hljs-params { color: #00F; } -pre .javascript .title, -pre .lisp .title, -pre .subst { +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { font-weight: normal } -pre .class .title, -pre .haskell .label, -pre .tex .command { +pre .hljs-class .hljs-title, +pre .hljs-haskell .hljs-label, +pre .hljs-tex .hljs-command { color: #458; font-weight: bold } -pre .tag, -pre .tag .title, -pre .rules .property, -pre .django .tag .keyword { +pre .hljs-tag, +pre .hljs-tag .hljs-title, +pre .hljs-rules .hljs-property, +pre .hljs-django .hljs-tag .hljs-keyword { color: #000080; font-weight: normal } -pre .attribute, -pre .variable, -pre .instancevar, -pre .lisp .body { +pre .hljs-attribute, +pre .hljs-variable, +pre .hljs-instancevar, +pre .hljs-lisp .hljs-body { color: #008080 } -pre .regexp { +pre .hljs-regexp { color: #B68 } -pre .class { +pre .hljs-class { color: #458; font-weight: bold } -pre .symbol, -pre .ruby .symbol .string, -pre .ruby .symbol .keyword, -pre .ruby .symbol .keymethods, -pre .lisp .keyword, -pre .tex .special, -pre .input_number { +pre .hljs-symbol, +pre .hljs-ruby .hljs-symbol .hljs-string, +pre .hljs-ruby .hljs-symbol .hljs-keyword, +pre .hljs-ruby .hljs-symbol .hljs-keymethods, +pre .hljs-lisp .hljs-keyword, +pre .hljs-tex .hljs-special, +pre .hljs-input_number { color: #990073 } -pre .builtin, -pre .constructor, -pre .built_in, -pre .lisp .title { +pre .hljs-builtin, +pre .hljs-constructor, +pre .hljs-built_in, +pre .hljs-lisp .hljs-title { color: #0086b3 } -pre .preprocessor, -pre .pi, -pre .doctype, -pre .shebang, -pre .cdata { +pre .hljs-preprocessor, +pre .hljs-pi, +pre .hljs-doctype, +pre .hljs-shebang, +pre .hljs-cdata { color: #999; font-weight: bold } -pre .deletion { +pre .hljs-deletion { background: #fdd } -pre .addition { +pre .hljs-addition { background: #dfd } -pre .diff .change { +pre .hljs-diff .hljs-change { background: #0086b3 } -pre .chunk { +pre .hljs-chunk { color: #aaa } -pre .tex .formula { +pre .hljs-tex .hljs-formula { opacity: 0.5; } diff --git a/docs/public/fonts/aller-bold.eot b/docs/public/fonts/aller-bold.eot old mode 100755 new mode 100644 diff --git a/docs/public/fonts/aller-bold.ttf b/docs/public/fonts/aller-bold.ttf old mode 100755 new mode 100644 diff --git a/docs/public/fonts/aller-bold.woff b/docs/public/fonts/aller-bold.woff old mode 100755 new mode 100644 diff --git a/docs/public/fonts/aller-light.eot b/docs/public/fonts/aller-light.eot old mode 100755 new mode 100644 diff --git a/docs/public/fonts/aller-light.ttf b/docs/public/fonts/aller-light.ttf old mode 100755 new mode 100644 diff --git a/docs/public/fonts/aller-light.woff b/docs/public/fonts/aller-light.woff old mode 100755 new mode 100644 diff --git a/docs/public/fonts/novecento-bold.eot b/docs/public/fonts/novecento-bold.eot old mode 100755 new mode 100644 diff --git a/docs/public/fonts/novecento-bold.ttf b/docs/public/fonts/novecento-bold.ttf old mode 100755 new mode 100644 diff --git a/docs/public/fonts/novecento-bold.woff b/docs/public/fonts/novecento-bold.woff old mode 100755 new mode 100644 diff --git a/docs/underscore.html b/docs/underscore.html index b96d40874..014d5dece 100644 --- a/docs/underscore.html +++ b/docs/underscore.html @@ -27,14 +27,15 @@

underscore.js

-
Underscore.js 1.5.2
-http://underscorejs.org
-(c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
-Underscore may be freely distributed under the MIT license.
- +
Underscore.js 1.6.0
+http://underscorejs.org
+(c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+Underscore may be freely distributed under the MIT license.
+
-
(function() {
+
+(function() {
@@ -42,10 +43,10 @@

underscore.js

  • -
    +
    -

    Baseline setup

    +

    Baseline setup

    @@ -58,12 +59,9 @@

    Baseline setup

    -

    Establish the root object, window in the browser, or exports on the server.

    - +
    -
      var root = this;
    -
  • @@ -73,11 +71,11 @@

    Baseline setup

    -

    Save the previous value of the _ variable.

    +

    Establish the root object, window in the browser, or exports on the server.

    -
      var previousUnderscore = root._;
    +
      var root = this;
    @@ -88,11 +86,11 @@

    Baseline setup

    -

    Establish the object that gets returned to break out of a loop iteration.

    +

    Save the previous value of the _ variable.

    -
      var breaker = {};
    +
      var previousUnderscore = root._;
    @@ -103,11 +101,11 @@

    Baseline setup

    -

    Save bytes in the minified (but not gzipped) version:

    +

    Establish the object that gets returned to break out of a loop iteration.

    -
      var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
    +
      var breaker = {};
    @@ -118,11 +116,26 @@

    Baseline setup

    +

    Save bytes in the minified (but not gzipped) version:

    + + + +
      var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
    + + + + +
  • +
    + +
    + +

    Create quick reference variables for speed access to core prototypes.

    -
      var
    +            
      var
         push             = ArrayProto.push,
         slice            = ArrayProto.slice,
         concat           = ArrayProto.concat,
    @@ -132,18 +145,18 @@ 

    Baseline setup

  • -
  • +
  • - +

    All ECMAScript 5 native function implementations that we hope to use are declared here.

    -
      var
    +            
      var
         nativeForEach      = ArrayProto.forEach,
         nativeMap          = ArrayProto.map,
         nativeReduce       = ArrayProto.reduce,
    @@ -153,653 +166,667 @@ 

    Baseline setup

    nativeSome = ArrayProto.some, nativeIndexOf = ArrayProto.indexOf, nativeLastIndexOf = ArrayProto.lastIndexOf, - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, nativeBind = FuncProto.bind;
  • -
  • +
  • - +

    Create a safe reference to the Underscore object for use below.

    -
      var _ = function(obj) {
    -    if (obj instanceof _) return obj;
    -    if (!(this instanceof _)) return new _(obj);
    -    this._wrapped = obj;
    +            
      var _ = function(obj) {
    +    if (obj instanceof _) return obj;
    +    if (!(this instanceof _)) return new _(obj);
    +    this._wrapped = obj;
       };
  • -
  • +
  • - +

    Export the Underscore object for Node.js, with -backwards-compatibility for the old require() API. If we're in +backwards-compatibility for the old require() API. If we’re in the browser, add _ as a global object via a string identifier, -for Closure Compiler "advanced" mode.

    +for Closure Compiler “advanced” mode.

    -
      if (typeof exports !== 'undefined') {
    -    if (typeof module !== 'undefined' && module.exports) {
    +            
      if (typeof exports !== 'undefined') {
    +    if (typeof module !== 'undefined' && module.exports) {
           exports = module.exports = _;
         }
         exports._ = _;
    -  } else {
    +  } else {
         root._ = _;
       }
  • -
  • +
  • - +

    Current version.

    -
      _.VERSION = '1.5.2';
    +
      _.VERSION = '1.6.0';
  • -
  • +
  • -
    - +
    +
    -

    Collection Functions

    +

    Collection Functions

  • -
  • +
  • - + +
    + +
    + +
  • + + +
  • +
    + +
    +

    The cornerstone, an each implementation, aka forEach. Handles objects with the built-in forEach, arrays, and raw objects. -Delegates to ECMAScript 5's native forEach if available.

    +Delegates to ECMAScript 5‘s native forEach if available.

    -
      var each = _.each = _.forEach = function(obj, iterator, context) {
    -    if (obj == null) return;
    -    if (nativeForEach && obj.forEach === nativeForEach) {
    +            
      var each = _.each = _.forEach = function(obj, iterator, context) {
    +    if (obj == null) return obj;
    +    if (nativeForEach && obj.forEach === nativeForEach) {
           obj.forEach(iterator, context);
    -    } else if (obj.length === +obj.length) {
    -      for (var i = 0, length = obj.length; i < length; i++) {
    -        if (iterator.call(context, obj[i], i, obj) === breaker) return;
    +    } else if (obj.length === +obj.length) {
    +      for (var i = 0, length = obj.length; i < length; i++) {
    +        if (iterator.call(context, obj[i], i, obj) === breaker) return;
           }
    -    } else {
    -      var keys = _.keys(obj);
    -      for (var i = 0, length = keys.length; i < length; i++) {
    -        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
    +    } else {
    +      var keys = _.keys(obj);
    +      for (var i = 0, length = keys.length; i < length; i++) {
    +        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
           }
         }
    +    return obj;
       };
  • -
  • +
  • - +

    Return the results of applying the iterator to each element. -Delegates to ECMAScript 5's native map if available.

    +Delegates to ECMAScript 5‘s native map if available.

    -
      _.map = _.collect = function(obj, iterator, context) {
    -    var results = [];
    -    if (obj == null) return results;
    -    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    -    each(obj, function(value, index, list) {
    +            
      _.map = _.collect = function(obj, iterator, context) {
    +    var results = [];
    +    if (obj == null) return results;
    +    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    +    each(obj, function(value, index, list) {
           results.push(iterator.call(context, value, index, list));
         });
    -    return results;
    +    return results;
       };
     
    -  var reduceError = 'Reduce of empty array with no initial value';
    + var reduceError = 'Reduce of empty array with no initial value';
  • -
  • +
  • - +

    Reduce builds up a single result from a list of values, aka inject, -or foldl. Delegates to ECMAScript 5's native reduce if available.

    +or foldl. Delegates to ECMAScript 5‘s native reduce if available.

    -
      _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    -    var initial = arguments.length > 2;
    -    if (obj == null) obj = [];
    -    if (nativeReduce && obj.reduce === nativeReduce) {
    -      if (context) iterator = _.bind(iterator, context);
    -      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    +            
      _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    +    var initial = arguments.length > 2;
    +    if (obj == null) obj = [];
    +    if (nativeReduce && obj.reduce === nativeReduce) {
    +      if (context) iterator = _.bind(iterator, context);
    +      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
         }
    -    each(obj, function(value, index, list) {
    -      if (!initial) {
    +    each(obj, function(value, index, list) {
    +      if (!initial) {
             memo = value;
    -        initial = true;
    -      } else {
    +        initial = true;
    +      } else {
             memo = iterator.call(context, memo, value, index, list);
           }
         });
    -    if (!initial) throw new TypeError(reduceError);
    -    return memo;
    +    if (!initial) throw new TypeError(reduceError);
    +    return memo;
       };
  • -
  • +
  • - +

    The right-associative version of reduce, also known as foldr. -Delegates to ECMAScript 5's native reduceRight if available.

    +Delegates to ECMAScript 5‘s native reduceRight if available.

    -
      _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
    -    var initial = arguments.length > 2;
    -    if (obj == null) obj = [];
    -    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
    -      if (context) iterator = _.bind(iterator, context);
    -      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
    +            
      _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
    +    var initial = arguments.length > 2;
    +    if (obj == null) obj = [];
    +    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
    +      if (context) iterator = _.bind(iterator, context);
    +      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
         }
    -    var length = obj.length;
    -    if (length !== +length) {
    -      var keys = _.keys(obj);
    +    var length = obj.length;
    +    if (length !== +length) {
    +      var keys = _.keys(obj);
           length = keys.length;
         }
    -    each(obj, function(value, index, list) {
    +    each(obj, function(value, index, list) {
           index = keys ? keys[--length] : --length;
    -      if (!initial) {
    +      if (!initial) {
             memo = obj[index];
    -        initial = true;
    -      } else {
    +        initial = true;
    +      } else {
             memo = iterator.call(context, memo, obj[index], index, list);
           }
         });
    -    if (!initial) throw new TypeError(reduceError);
    -    return memo;
    +    if (!initial) throw new TypeError(reduceError);
    +    return memo;
       };
  • -
  • +
  • - +

    Return the first value which passes a truth test. Aliased as detect.

    -
      _.find = _.detect = function(obj, iterator, context) {
    -    var result;
    -    any(obj, function(value, index, list) {
    -      if (iterator.call(context, value, index, list)) {
    +            
      _.find = _.detect = function(obj, predicate, context) {
    +    var result;
    +    any(obj, function(value, index, list) {
    +      if (predicate.call(context, value, index, list)) {
             result = value;
    -        return true;
    +        return true;
           }
         });
    -    return result;
    +    return result;
       };
  • -
  • +
  • - +

    Return all the elements that pass a truth test. -Delegates to ECMAScript 5's native filter if available. +Delegates to ECMAScript 5‘s native filter if available. Aliased as select.

    -
      _.filter = _.select = function(obj, iterator, context) {
    -    var results = [];
    -    if (obj == null) return results;
    -    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    -    each(obj, function(value, index, list) {
    -      if (iterator.call(context, value, index, list)) results.push(value);
    +            
      _.filter = _.select = function(obj, predicate, context) {
    +    var results = [];
    +    if (obj == null) return results;
    +    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
    +    each(obj, function(value, index, list) {
    +      if (predicate.call(context, value, index, list)) results.push(value);
         });
    -    return results;
    +    return results;
       };
  • -
  • +
  • - +

    Return all the elements for which a truth test fails.

    -
      _.reject = function(obj, iterator, context) {
    -    return _.filter(obj, function(value, index, list) {
    -      return !iterator.call(context, value, index, list);
    +            
      _.reject = function(obj, predicate, context) {
    +    return _.filter(obj, function(value, index, list) {
    +      return !predicate.call(context, value, index, list);
         }, context);
       };
  • -
  • +
  • - +

    Determine whether all of the elements match a truth test. -Delegates to ECMAScript 5's native every if available. +Delegates to ECMAScript 5‘s native every if available. Aliased as all.

    -
      _.every = _.all = function(obj, iterator, context) {
    -    iterator || (iterator = _.identity);
    -    var result = true;
    -    if (obj == null) return result;
    -    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    -    each(obj, function(value, index, list) {
    -      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
    +            
      _.every = _.all = function(obj, predicate, context) {
    +    predicate || (predicate = _.identity);
    +    var result = true;
    +    if (obj == null) return result;
    +    if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
    +    each(obj, function(value, index, list) {
    +      if (!(result = result && predicate.call(context, value, index, list))) return breaker;
         });
    -    return !!result;
    +    return !!result;
       };
  • -
  • +
  • - +

    Determine if at least one element in the object matches a truth test. -Delegates to ECMAScript 5's native some if available. +Delegates to ECMAScript 5‘s native some if available. Aliased as any.

    -
      var any = _.some = _.any = function(obj, iterator, context) {
    -    iterator || (iterator = _.identity);
    -    var result = false;
    -    if (obj == null) return result;
    -    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    -    each(obj, function(value, index, list) {
    -      if (result || (result = iterator.call(context, value, index, list))) return breaker;
    +            
      var any = _.some = _.any = function(obj, predicate, context) {
    +    predicate || (predicate = _.identity);
    +    var result = false;
    +    if (obj == null) return result;
    +    if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
    +    each(obj, function(value, index, list) {
    +      if (result || (result = predicate.call(context, value, index, list))) return breaker;
         });
    -    return !!result;
    +    return !!result;
       };
  • -
  • +
  • - +

    Determine if the array or object contains a given value (using ===). Aliased as include.

    -
      _.contains = _.include = function(obj, target) {
    -    if (obj == null) return false;
    -    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    -    return any(obj, function(value) {
    -      return value === target;
    +            
      _.contains = _.include = function(obj, target) {
    +    if (obj == null) return false;
    +    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    +    return any(obj, function(value) {
    +      return value === target;
         });
       };
  • -
  • +
  • - +

    Invoke a method (with arguments) on every item in a collection.

    -
      _.invoke = function(obj, method) {
    -    var args = slice.call(arguments, 2);
    -    var isFunc = _.isFunction(method);
    -    return _.map(obj, function(value) {
    -      return (isFunc ? method : value[method]).apply(value, args);
    +            
      _.invoke = function(obj, method) {
    +    var args = slice.call(arguments, 2);
    +    var isFunc = _.isFunction(method);
    +    return _.map(obj, function(value) {
    +      return (isFunc ? method : value[method]).apply(value, args);
         });
       };
  • -
  • +
  • - +

    Convenience version of a common use case of map: fetching a property.

    -
      _.pluck = function(obj, key) {
    -    return _.map(obj, function(value){ return value[key]; });
    +            
      _.pluck = function(obj, key) {
    +    return _.map(obj, _.property(key));
       };
  • -
  • +
  • - +

    Convenience version of a common use case of filter: selecting only objects containing specific key:value pairs.

    -
      _.where = function(obj, attrs, first) {
    -    if (_.isEmpty(attrs)) return first ? void 0 : [];
    -    return _[first ? 'find' : 'filter'](obj, function(value) {
    -      for (var key in attrs) {
    -        if (attrs[key] !== value[key]) return false;
    -      }
    -      return true;
    -    });
    +            
      _.where = function(obj, attrs) {
    +    return _.filter(obj, _.matches(attrs));
       };
  • -
  • +
  • - +

    Convenience version of a common use case of find: getting the first object containing specific key:value pairs.

    -
      _.findWhere = function(obj, attrs) {
    -    return _.where(obj, attrs, true);
    +            
      _.findWhere = function(obj, attrs) {
    +    return _.find(obj, _.matches(attrs));
       };
  • -
  • +
  • - +

    Return the maximum element or (element-based computation). -Can't optimize arrays of integers longer than 65,535 elements. +Can’t optimize arrays of integers longer than 65,535 elements. See WebKit Bug 80797

    -
      _.max = function(obj, iterator, context) {
    -    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    -      return Math.max.apply(Math, obj);
    +            
      _.max = function(obj, iterator, context) {
    +    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    +      return Math.max.apply(Math, obj);
         }
    -    if (!iterator && _.isEmpty(obj)) return -Infinity;
    -    var result = {computed : -Infinity, value: -Infinity};
    -    each(obj, function(value, index, list) {
    -      var computed = iterator ? iterator.call(context, value, index, list) : value;
    -      computed > result.computed && (result = {value : value, computed : computed});
    +    var result = -Infinity, lastComputed = -Infinity;
    +    each(obj, function(value, index, list) {
    +      var computed = iterator ? iterator.call(context, value, index, list) : value;
    +      if (computed > lastComputed) {
    +        result = value;
    +        lastComputed = computed;
    +      }
         });
    -    return result.value;
    +    return result;
       };
  • -
  • +
  • - +

    Return the minimum element (or element-based computation).

    -
      _.min = function(obj, iterator, context) {
    -    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    -      return Math.min.apply(Math, obj);
    +            
      _.min = function(obj, iterator, context) {
    +    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    +      return Math.min.apply(Math, obj);
         }
    -    if (!iterator && _.isEmpty(obj)) return Infinity;
    -    var result = {computed : Infinity, value: Infinity};
    -    each(obj, function(value, index, list) {
    -      var computed = iterator ? iterator.call(context, value, index, list) : value;
    -      computed < result.computed && (result = {value : value, computed : computed});
    +    var result = Infinity, lastComputed = Infinity;
    +    each(obj, function(value, index, list) {
    +      var computed = iterator ? iterator.call(context, value, index, list) : value;
    +      if (computed < lastComputed) {
    +        result = value;
    +        lastComputed = computed;
    +      }
         });
    -    return result.value;
    +    return result;
       };
  • -
  • +
  • - +
    -

    Shuffle an array, using the modern version of the +

    Shuffle an array, using the modern version of the Fisher-Yates shuffle.

    -
      _.shuffle = function(obj) {
    -    var rand;
    -    var index = 0;
    -    var shuffled = [];
    -    each(obj, function(value) {
    +            
      _.shuffle = function(obj) {
    +    var rand;
    +    var index = 0;
    +    var shuffled = [];
    +    each(obj, function(value) {
           rand = _.random(index++);
    -      shuffled[index - 1] = shuffled[rand];
    +      shuffled[index - 1] = shuffled[rand];
           shuffled[rand] = value;
         });
    -    return shuffled;
    +    return shuffled;
       };
  • -
  • +
  • - +
    -

    Sample n random values from an array. -If n is not specified, returns a single random element from the array. +

    Sample n random values from a collection. +If n is not specified, returns a single random element. The internal guard argument allows it to work with map.

    -
      _.sample = function(obj, n, guard) {
    -    if (arguments.length < 2 || guard) {
    -      return obj[_.random(obj.length - 1)];
    +            
      _.sample = function(obj, n, guard) {
    +    if (n == null || guard) {
    +      if (obj.length !== +obj.length) obj = _.values(obj);
    +      return obj[_.random(obj.length - 1)];
         }
    -    return _.shuffle(obj).slice(0, Math.max(0, n));
    +    return _.shuffle(obj).slice(0, Math.max(0, n));
       };
  • -
  • +
  • - +

    An internal function to generate lookup iterators.

    -
      var lookupIterator = function(value) {
    -    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
    +            
      var lookupIterator = function(value) {
    +    if (value == null) return _.identity;
    +    if (_.isFunction(value)) return value;
    +    return _.property(value);
       };
  • -
  • +
  • - +
    -

    Sort the object's values by a criterion produced by an iterator.

    +

    Sort the object’s values by a criterion produced by an iterator.

    -
      _.sortBy = function(obj, value, context) {
    -    var iterator = lookupIterator(value);
    -    return _.pluck(_.map(obj, function(value, index, list) {
    -      return {
    +            
      _.sortBy = function(obj, iterator, context) {
    +    iterator = lookupIterator(iterator);
    +    return _.pluck(_.map(obj, function(value, index, list) {
    +      return {
             value: value,
             index: index,
             criteria: iterator.call(context, value, index, list)
           };
    -    }).sort(function(left, right) {
    -      var a = left.criteria;
    -      var b = right.criteria;
    -      if (a !== b) {
    -        if (a > b || a === void 0) return 1;
    -        if (a < b || b === void 0) return -1;
    +    }).sort(function(left, right) {
    +      var a = left.criteria;
    +      var b = right.criteria;
    +      if (a !== b) {
    +        if (a > b || a === void 0) return 1;
    +        if (a < b || b === void 0) return -1;
           }
    -      return left.index - right.index;
    -    }), 'value');
    +      return left.index - right.index;
    +    }), 'value');
       };
  • -
  • +
  • - +
    -

    An internal function used for aggregate "group by" operations.

    +

    An internal function used for aggregate “group by” operations.

    -
      var group = function(behavior) {
    -    return function(obj, value, context) {
    -      var result = {};
    -      var iterator = value == null ? _.identity : lookupIterator(value);
    -      each(obj, function(value, index) {
    -        var key = iterator.call(context, value, index, obj);
    +            
      var group = function(behavior) {
    +    return function(obj, iterator, context) {
    +      var result = {};
    +      iterator = lookupIterator(iterator);
    +      each(obj, function(value, index) {
    +        var key = iterator.call(context, value, index, obj);
             behavior(result, key, value);
           });
    -      return result;
    +      return result;
         };
       };
  • -
  • +
  • - +
    -

    Groups the object's values by a criterion. Pass either a string attribute +

    Groups the object’s values by a criterion. Pass either a string attribute to group by, or a function that returns the criterion.

    -
      _.groupBy = group(function(result, key, value) {
    -    (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
    +            
      _.groupBy = group(function(result, key, value) {
    +    _.has(result, key) ? result[key].push(value) : result[key] = [value];
       });
  • -
  • +
  • - +
    -

    Indexes the object's values by a criterion, similar to groupBy, but for +

    Indexes the object’s values by a criterion, similar to groupBy, but for when you know that your index values will be unique.

    -
      _.indexBy = group(function(result, key, value) {
    +            
      _.indexBy = group(function(result, key, value) {
         result[key] = value;
       });
  • -
  • +
  • - +

    Counts instances of an object that group by a certain criterion. Pass either a string attribute to count by, or a function that returns the @@ -807,94 +834,106 @@

    Collection Functions

    -
      _.countBy = group(function(result, key) {
    -    _.has(result, key) ? result[key]++ : result[key] = 1;
    +            
      _.countBy = group(function(result, key) {
    +    _.has(result, key) ? result[key]++ : result[key] = 1;
       });
  • -
  • +
  • - +

    Use a comparator function to figure out the smallest index at which an object should be inserted so as to maintain order. Uses binary search.

    -
      _.sortedIndex = function(array, obj, iterator, context) {
    -    iterator = iterator == null ? _.identity : lookupIterator(iterator);
    -    var value = iterator.call(context, obj);
    -    var low = 0, high = array.length;
    -    while (low < high) {
    -      var mid = (low + high) >>> 1;
    -      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
    +            
      _.sortedIndex = function(array, obj, iterator, context) {
    +    iterator = lookupIterator(iterator);
    +    var value = iterator.call(context, obj);
    +    var low = 0, high = array.length;
    +    while (low < high) {
    +      var mid = (low + high) >>> 1;
    +      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
         }
    -    return low;
    +    return low;
       };
  • -
  • +
  • - +

    Safely create a real, live array from anything iterable.

    -
      _.toArray = function(obj) {
    -    if (!obj) return [];
    -    if (_.isArray(obj)) return slice.call(obj);
    -    if (obj.length === +obj.length) return _.map(obj, _.identity);
    -    return _.values(obj);
    +            
      _.toArray = function(obj) {
    +    if (!obj) return [];
    +    if (_.isArray(obj)) return slice.call(obj);
    +    if (obj.length === +obj.length) return _.map(obj, _.identity);
    +    return _.values(obj);
       };
  • -
  • +
  • - +

    Return the number of elements in an object.

    -
      _.size = function(obj) {
    -    if (obj == null) return 0;
    -    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
    +            
      _.size = function(obj) {
    +    if (obj == null) return 0;
    +    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
       };
  • -
  • +
  • -
    - +
    +
    -

    Array Functions

    +

    Array Functions

  • -
  • +
  • - + +
    + +
    + +
  • + + +
  • +
    + +
    +

    Get the first element of an array. Passing n will return the first N values in the array. Aliased as head and take. The guard check @@ -902,19 +941,21 @@

    Array Functions

    -
      _.first = _.head = _.take = function(array, n, guard) {
    -    if (array == null) return void 0;
    -    return (n == null) || guard ? array[0] : slice.call(array, 0, n);
    +            
      _.first = _.head = _.take = function(array, n, guard) {
    +    if (array == null) return void 0;
    +    if ((n == null) || guard) return array[0];
    +    if (n < 0) return [];
    +    return slice.call(array, 0, n);
       };
  • -
  • +
  • - +

    Returns everything but the last entry of the array. Especially useful on the arguments object. Passing n will return all the values in @@ -923,41 +964,38 @@

    Array Functions

    -
      _.initial = function(array, n, guard) {
    -    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
    +            
      _.initial = function(array, n, guard) {
    +    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
       };
  • -
  • +
  • - +

    Get the last element of an array. Passing n will return the last N values in the array. The guard check allows it to work with _.map.

    -
      _.last = function(array, n, guard) {
    -    if (array == null) return void 0;
    -    if ((n == null) || guard) {
    -      return array[array.length - 1];
    -    } else {
    -      return slice.call(array, Math.max(array.length - n, 0));
    -    }
    +            
      _.last = function(array, n, guard) {
    +    if (array == null) return void 0;
    +    if ((n == null) || guard) return array[array.length - 1];
    +    return slice.call(array, Math.max(array.length - n, 0));
       };
  • -
  • +
  • - +

    Returns everything but the first entry of the array. Aliased as tail and drop. Especially useful on the arguments object. Passing an n will return @@ -966,96 +1004,118 @@

    Array Functions

    -
      _.rest = _.tail = _.drop = function(array, n, guard) {
    -    return slice.call(array, (n == null) || guard ? 1 : n);
    +            
      _.rest = _.tail = _.drop = function(array, n, guard) {
    +    return slice.call(array, (n == null) || guard ? 1 : n);
       };
  • -
  • +
  • - +

    Trim out all falsy values from an array.

    -
      _.compact = function(array) {
    -    return _.filter(array, _.identity);
    +            
      _.compact = function(array) {
    +    return _.filter(array, _.identity);
       };
  • -
  • +
  • - +

    Internal implementation of a recursive flatten function.

    -
      var flatten = function(input, shallow, output) {
    -    if (shallow && _.every(input, _.isArray)) {
    -      return concat.apply(output, input);
    +            
      var flatten = function(input, shallow, output) {
    +    if (shallow && _.every(input, _.isArray)) {
    +      return concat.apply(output, input);
         }
    -    each(input, function(value) {
    -      if (_.isArray(value) || _.isArguments(value)) {
    +    each(input, function(value) {
    +      if (_.isArray(value) || _.isArguments(value)) {
             shallow ? push.apply(output, value) : flatten(value, shallow, output);
    -      } else {
    +      } else {
             output.push(value);
           }
         });
    -    return output;
    +    return output;
       };
  • -
  • +
  • - +

    Flatten out an array, either recursively (by default), or just one level.

    -
      _.flatten = function(array, shallow) {
    -    return flatten(array, shallow, []);
    +            
      _.flatten = function(array, shallow) {
    +    return flatten(array, shallow, []);
       };
  • -
  • +
  • - +

    Return a version of the array that does not contain the specified value(s).

    -
      _.without = function(array) {
    -    return _.difference(array, slice.call(arguments, 1));
    +            
      _.without = function(array) {
    +    return _.difference(array, slice.call(arguments, 1));
       };
  • -
  • +
  • - + +
    +

    Split an array into two arrays: one whose elements all satisfy the given +predicate, and one whose elements all do not satisfy the predicate.

    + +
    + +
      _.partition = function(array, predicate) {
    +    var pass = [], fail = [];
    +    each(array, function(elem) {
    +      (predicate(elem) ? pass : fail).push(elem);
    +    });
    +    return [pass, fail];
    +  };
    + +
  • + + +
  • +
    + +
    +

    Produce a duplicate-free version of the array. If the array has already been sorted, you have the option of using a faster algorithm. @@ -1063,61 +1123,61 @@

    Array Functions

    -
      _.uniq = _.unique = function(array, isSorted, iterator, context) {
    -    if (_.isFunction(isSorted)) {
    +            
      _.uniq = _.unique = function(array, isSorted, iterator, context) {
    +    if (_.isFunction(isSorted)) {
           context = iterator;
           iterator = isSorted;
    -      isSorted = false;
    +      isSorted = false;
         }
    -    var initial = iterator ? _.map(array, iterator, context) : array;
    -    var results = [];
    -    var seen = [];
    -    each(initial, function(value, index) {
    -      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
    +    var initial = iterator ? _.map(array, iterator, context) : array;
    +    var results = [];
    +    var seen = [];
    +    each(initial, function(value, index) {
    +      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
             seen.push(value);
             results.push(array[index]);
           }
         });
    -    return results;
    +    return results;
       };
  • -
  • +
  • - +

    Produce an array that contains the union: each distinct element from all of the passed-in arrays.

    -
      _.union = function() {
    -    return _.uniq(_.flatten(arguments, true));
    +            
      _.union = function() {
    +    return _.uniq(_.flatten(arguments, true));
       };
  • -
  • +
  • - +

    Produce an array that contains every item shared between all the passed-in arrays.

    -
      _.intersection = function(array) {
    -    var rest = slice.call(arguments, 1);
    -    return _.filter(_.uniq(array), function(item) {
    -      return _.every(rest, function(other) {
    -        return _.indexOf(other, item) >= 0;
    +            
      _.intersection = function(array) {
    +    var rest = slice.call(arguments, 1);
    +    return _.filter(_.uniq(array), function(item) {
    +      return _.every(rest, function(other) {
    +        return _.contains(other, item);
           });
         });
       };
    @@ -1125,139 +1185,139 @@

    Array Functions

  • -
  • +
  • - +

    Take the difference between one array and a number of other arrays. Only the elements present in just the first array will remain.

    -
      _.difference = function(array) {
    -    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
    -    return _.filter(array, function(value){ return !_.contains(rest, value); });
    +            
      _.difference = function(array) {
    +    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
    +    return _.filter(array, function(value){ return !_.contains(rest, value); });
       };
  • -
  • +
  • - +
    -

    Zip together multiple lists into a single array -- elements that share +

    Zip together multiple lists into a single array — elements that share an index go together.

    -
      _.zip = function() {
    -    var length = _.max(_.pluck(arguments, "length").concat(0));
    -    var results = new Array(length);
    -    for (var i = 0; i < length; i++) {
    -      results[i] = _.pluck(arguments, '' + i);
    +            
      _.zip = function() {
    +    var length = _.max(_.pluck(arguments, 'length').concat(0));
    +    var results = new Array(length);
    +    for (var i = 0; i < length; i++) {
    +      results[i] = _.pluck(arguments, '' + i);
         }
    -    return results;
    +    return results;
       };
  • -
  • +
  • - +

    Converts lists into objects. Pass either a single array of [key, value] -pairs, or two parallel arrays of the same length -- one of keys, and one of +pairs, or two parallel arrays of the same length — one of keys, and one of the corresponding values.

    -
      _.object = function(list, values) {
    -    if (list == null) return {};
    -    var result = {};
    -    for (var i = 0, length = list.length; i < length; i++) {
    -      if (values) {
    +            
      _.object = function(list, values) {
    +    if (list == null) return {};
    +    var result = {};
    +    for (var i = 0, length = list.length; i < length; i++) {
    +      if (values) {
             result[list[i]] = values[i];
    -      } else {
    -        result[list[i][0]] = list[i][1];
    +      } else {
    +        result[list[i][0]] = list[i][1];
           }
         }
    -    return result;
    +    return result;
       };
  • -
  • +
  • - +
    -

    If the browser doesn't supply us with indexOf (I'm looking at you, MSIE), +

    If the browser doesn’t supply us with indexOf (I’m looking at you, MSIE), we need this function. Return the position of the first occurrence of an item in an array, or -1 if the item is not included in the array. -Delegates to ECMAScript 5's native indexOf if available. +Delegates to ECMAScript 5‘s native indexOf if available. If the array is large and already in sort order, pass true for isSorted to use binary search.

    -
      _.indexOf = function(array, item, isSorted) {
    -    if (array == null) return -1;
    -    var i = 0, length = array.length;
    -    if (isSorted) {
    -      if (typeof isSorted == 'number') {
    -        i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
    -      } else {
    +            
      _.indexOf = function(array, item, isSorted) {
    +    if (array == null) return -1;
    +    var i = 0, length = array.length;
    +    if (isSorted) {
    +      if (typeof isSorted == 'number') {
    +        i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
    +      } else {
             i = _.sortedIndex(array, item);
    -        return array[i] === item ? i : -1;
    +        return array[i] === item ? i : -1;
           }
         }
    -    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
    -    for (; i < length; i++) if (array[i] === item) return i;
    -    return -1;
    +    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
    +    for (; i < length; i++) if (array[i] === item) return i;
    +    return -1;
       };
  • -
  • +
  • - +
    -

    Delegates to ECMAScript 5's native lastIndexOf if available.

    +

    Delegates to ECMAScript 5‘s native lastIndexOf if available.

    -
      _.lastIndexOf = function(array, item, from) {
    -    if (array == null) return -1;
    -    var hasIndex = from != null;
    -    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
    -      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
    +            
      _.lastIndexOf = function(array, item, from) {
    +    if (array == null) return -1;
    +    var hasIndex = from != null;
    +    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
    +      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
         }
    -    var i = (hasIndex ? from : array.length);
    -    while (i--) if (array[i] === item) return i;
    -    return -1;
    +    var i = (hasIndex ? from : array.length);
    +    while (i--) if (array[i] === item) return i;
    +    return -1;
       };
  • -
  • +
  • - +

    Generate an integer Array containing an arithmetic progression. A port of the native Python range() function. See @@ -1265,238 +1325,260 @@

    Array Functions

    -
      _.range = function(start, stop, step) {
    -    if (arguments.length <= 1) {
    -      stop = start || 0;
    -      start = 0;
    +            
      _.range = function(start, stop, step) {
    +    if (arguments.length <= 1) {
    +      stop = start || 0;
    +      start = 0;
         }
    -    step = arguments[2] || 1;
    +    step = arguments[2] || 1;
     
    -    var length = Math.max(Math.ceil((stop - start) / step), 0);
    -    var idx = 0;
    -    var range = new Array(length);
    +    var length = Math.max(Math.ceil((stop - start) / step), 0);
    +    var idx = 0;
    +    var range = new Array(length);
     
    -    while(idx < length) {
    +    while(idx < length) {
           range[idx++] = start;
           start += step;
         }
     
    -    return range;
    +    return range;
       };
  • -
  • +
  • -
    - +
    +
    -

    Function (ahem) Functions

    +

    Function (ahem) Functions

  • -
  • +
  • - + +
    + +
    + +
  • + + +
  • +
    + +
    +

    Reusable constructor function for prototype setting.

    -
      var ctor = function(){};
    +
      var ctor = function(){};
  • -
  • +
  • - +

    Create a function bound to a given object (assigning this, and arguments, -optionally). Delegates to ECMAScript 5's native Function.bind if +optionally). Delegates to ECMAScript 5‘s native Function.bind if available.

    -
      _.bind = function(func, context) {
    -    var args, bound;
    -    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    -    if (!_.isFunction(func)) throw new TypeError;
    -    args = slice.call(arguments, 2);
    -    return bound = function() {
    -      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
    +            
      _.bind = function(func, context) {
    +    var args, bound;
    +    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    +    if (!_.isFunction(func)) throw new TypeError;
    +    args = slice.call(arguments, 2);
    +    return bound = function() {
    +      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
           ctor.prototype = func.prototype;
    -      var self = new ctor;
    -      ctor.prototype = null;
    -      var result = func.apply(self, args.concat(slice.call(arguments)));
    -      if (Object(result) === result) return result;
    -      return self;
    +      var self = new ctor;
    +      ctor.prototype = null;
    +      var result = func.apply(self, args.concat(slice.call(arguments)));
    +      if (Object(result) === result) return result;
    +      return self;
         };
       };
  • -
  • +
  • - +

    Partially apply a function by creating a version that has had some of its -arguments pre-filled, without changing its dynamic this context.

    +arguments pre-filled, without changing its dynamic this context. _ acts +as a placeholder, allowing any combination of arguments to be pre-filled.

    -
      _.partial = function(func) {
    -    var args = slice.call(arguments, 1);
    -    return function() {
    -      return func.apply(this, args.concat(slice.call(arguments)));
    +            
      _.partial = function(func) {
    +    var boundArgs = slice.call(arguments, 1);
    +    return function() {
    +      var position = 0;
    +      var args = boundArgs.slice();
    +      for (var i = 0, length = args.length; i < length; i++) {
    +        if (args[i] === _) args[i] = arguments[position++];
    +      }
    +      while (position < arguments.length) args.push(arguments[position++]);
    +      return func.apply(this, args);
         };
       };
  • -
  • +
  • - +
    -

    Bind all of an object's methods to that object. Useful for ensuring that -all callbacks defined on an object belong to it.

    +

    Bind a number of an object’s methods to that object. Remaining arguments +are the method names to be bound. Useful for ensuring that all callbacks +defined on an object belong to it.

    -
      _.bindAll = function(obj) {
    -    var funcs = slice.call(arguments, 1);
    -    if (funcs.length === 0) throw new Error("bindAll must be passed function names");
    -    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    -    return obj;
    +            
      _.bindAll = function(obj) {
    +    var funcs = slice.call(arguments, 1);
    +    if (funcs.length === 0) throw new Error('bindAll must be passed function names');
    +    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    +    return obj;
       };
  • -
  • +
  • - +

    Memoize an expensive function by storing its results.

    -
      _.memoize = function(func, hasher) {
    -    var memo = {};
    +            
      _.memoize = function(func, hasher) {
    +    var memo = {};
         hasher || (hasher = _.identity);
    -    return function() {
    -      var key = hasher.apply(this, arguments);
    -      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    +    return function() {
    +      var key = hasher.apply(this, arguments);
    +      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
         };
       };
  • -
  • +
  • - +

    Delays a function for the given number of milliseconds, and then calls it with the arguments supplied.

    -
      _.delay = function(func, wait) {
    -    var args = slice.call(arguments, 2);
    -    return setTimeout(function(){ return func.apply(null, args); }, wait);
    +            
      _.delay = function(func, wait) {
    +    var args = slice.call(arguments, 2);
    +    return setTimeout(function(){ return func.apply(null, args); }, wait);
       };
  • -
  • +
  • - +

    Defers a function, scheduling it to run after the current call stack has cleared.

    -
      _.defer = function(func) {
    -    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
    +            
      _.defer = function(func) {
    +    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
       };
  • -
  • +
  • - +

    Returns a function, that, when invoked, will only be triggered at most once during a given window of time. Normally, the throttled function will run as much as it can, without ever going more than once per wait duration; -but if you'd like to disable the execution on the leading edge, pass +but if you’d like to disable the execution on the leading edge, pass {leading: false}. To disable execution on the trailing edge, ditto.

    -
      _.throttle = function(func, wait, options) {
    -    var context, args, result;
    -    var timeout = null;
    -    var previous = 0;
    +            
      _.throttle = function(func, wait, options) {
    +    var context, args, result;
    +    var timeout = null;
    +    var previous = 0;
         options || (options = {});
    -    var later = function() {
    -      previous = options.leading === false ? 0 : new Date;
    -      timeout = null;
    +    var later = function() {
    +      previous = options.leading === false ? 0 : _.now();
    +      timeout = null;
           result = func.apply(context, args);
    +      context = args = null;
         };
    -    return function() {
    -      var now = new Date;
    -      if (!previous && options.leading === false) previous = now;
    -      var remaining = wait - (now - previous);
    -      context = this;
    -      args = arguments;
    -      if (remaining <= 0) {
    +    return function() {
    +      var now = _.now();
    +      if (!previous && options.leading === false) previous = now;
    +      var remaining = wait - (now - previous);
    +      context = this;
    +      args = arguments;
    +      if (remaining <= 0) {
             clearTimeout(timeout);
    -        timeout = null;
    +        timeout = null;
             previous = now;
             result = func.apply(context, args);
    -      } else if (!timeout && options.trailing !== false) {
    +        context = args = null;
    +      } else if (!timeout && options.trailing !== false) {
             timeout = setTimeout(later, remaining);
           }
    -      return result;
    +      return result;
         };
       };
  • -
  • +
  • - +

    Returns a function, that, as long as it continues to be invoked, will not be triggered. The function will be called after it stops being called for @@ -1505,63 +1587,72 @@

    Function (ahem) Functions

    -
      _.debounce = function(func, wait, immediate) {
    -    var timeout, args, context, timestamp, result;
    -    return function() {
    -      context = this;
    -      args = arguments;
    -      timestamp = new Date();
    -      var later = function() {
    -        var last = (new Date()) - timestamp;
    -        if (last < wait) {
    -          timeout = setTimeout(later, wait - last);
    -        } else {
    -          timeout = null;
    -          if (!immediate) result = func.apply(context, args);
    +            
      _.debounce = function(func, wait, immediate) {
    +    var timeout, args, context, timestamp, result;
    +
    +    var later = function() {
    +      var last = _.now() - timestamp;
    +      if (last < wait) {
    +        timeout = setTimeout(later, wait - last);
    +      } else {
    +        timeout = null;
    +        if (!immediate) {
    +          result = func.apply(context, args);
    +          context = args = null;
             }
    -      };
    -      var callNow = immediate && !timeout;
    -      if (!timeout) {
    +      }
    +    };
    +
    +    return function() {
    +      context = this;
    +      args = arguments;
    +      timestamp = _.now();
    +      var callNow = immediate && !timeout;
    +      if (!timeout) {
             timeout = setTimeout(later, wait);
           }
    -      if (callNow) result = func.apply(context, args);
    -      return result;
    +      if (callNow) {
    +        result = func.apply(context, args);
    +        context = args = null;
    +      }
    +
    +      return result;
         };
       };
  • -
  • +
  • - +

    Returns a function that will be executed at most one time, no matter how often you call it. Useful for lazy initialization.

    -
      _.once = function(func) {
    -    var ran = false, memo;
    -    return function() {
    -      if (ran) return memo;
    -      ran = true;
    -      memo = func.apply(this, arguments);
    -      func = null;
    -      return memo;
    +            
      _.once = function(func) {
    +    var ran = false, memo;
    +    return function() {
    +      if (ran) return memo;
    +      ran = true;
    +      memo = func.apply(this, arguments);
    +      func = null;
    +      return memo;
         };
       };
  • -
  • +
  • - +

    Returns the first function passed as an argument to the second, allowing you to adjust arguments, run code before and after, and @@ -1569,56 +1660,52 @@

    Function (ahem) Functions

    -
      _.wrap = function(func, wrapper) {
    -    return function() {
    -      var args = [func];
    -      push.apply(args, arguments);
    -      return wrapper.apply(this, args);
    -    };
    +            
      _.wrap = function(func, wrapper) {
    +    return _.partial(wrapper, func);
       };
  • -
  • +
  • - +

    Returns a function that is the composition of a list of functions, each consuming the return value of the function that follows.

    -
      _.compose = function() {
    -    var funcs = arguments;
    -    return function() {
    -      var args = arguments;
    -      for (var i = funcs.length - 1; i >= 0; i--) {
    -        args = [funcs[i].apply(this, args)];
    +            
      _.compose = function() {
    +    var funcs = arguments;
    +    return function() {
    +      var args = arguments;
    +      for (var i = funcs.length - 1; i >= 0; i--) {
    +        args = [funcs[i].apply(this, args)];
           }
    -      return args[0];
    +      return args[0];
         };
       };
  • -
  • +
  • - +

    Returns a function that will only be executed after being called N times.

    -
      _.after = function(times, func) {
    -    return function() {
    -      if (--times < 1) {
    -        return func.apply(this, arguments);
    +            
      _.after = function(times, func) {
    +    return function() {
    +      if (--times < 1) {
    +        return func.apply(this, arguments);
           }
         };
       };
    @@ -1626,394 +1713,407 @@

    Function (ahem) Functions

  • -
  • +
  • -
    - +
    +
    -

    Object Functions

    +

    Object Functions

  • -
  • +
  • - + +
    + +
    + +
  • + + +
  • +
    + +
    +
    -

    Retrieve the names of an object's properties. -Delegates to ECMAScript 5's native Object.keys

    +

    Retrieve the names of an object’s properties. +Delegates to ECMAScript 5‘s native Object.keys

    -
      _.keys = nativeKeys || function(obj) {
    -    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    -    var keys = [];
    -    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    -    return keys;
    +            
      _.keys = function(obj) {
    +    if (!_.isObject(obj)) return [];
    +    if (nativeKeys) return nativeKeys(obj);
    +    var keys = [];
    +    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    +    return keys;
       };
  • -
  • +
  • - +
    -

    Retrieve the values of an object's properties.

    +

    Retrieve the values of an object’s properties.

    -
      _.values = function(obj) {
    -    var keys = _.keys(obj);
    -    var length = keys.length;
    -    var values = new Array(length);
    -    for (var i = 0; i < length; i++) {
    +            
      _.values = function(obj) {
    +    var keys = _.keys(obj);
    +    var length = keys.length;
    +    var values = new Array(length);
    +    for (var i = 0; i < length; i++) {
           values[i] = obj[keys[i]];
         }
    -    return values;
    +    return values;
       };
  • -
  • +
  • - +

    Convert an object into a list of [key, value] pairs.

    -
      _.pairs = function(obj) {
    -    var keys = _.keys(obj);
    -    var length = keys.length;
    -    var pairs = new Array(length);
    -    for (var i = 0; i < length; i++) {
    +            
      _.pairs = function(obj) {
    +    var keys = _.keys(obj);
    +    var length = keys.length;
    +    var pairs = new Array(length);
    +    for (var i = 0; i < length; i++) {
           pairs[i] = [keys[i], obj[keys[i]]];
         }
    -    return pairs;
    +    return pairs;
       };
  • -
  • +
  • - +

    Invert the keys and values of an object. The values must be serializable.

    -
      _.invert = function(obj) {
    -    var result = {};
    -    var keys = _.keys(obj);
    -    for (var i = 0, length = keys.length; i < length; i++) {
    +            
      _.invert = function(obj) {
    +    var result = {};
    +    var keys = _.keys(obj);
    +    for (var i = 0, length = keys.length; i < length; i++) {
           result[obj[keys[i]]] = keys[i];
         }
    -    return result;
    +    return result;
       };
  • -
  • +
  • - +

    Return a sorted list of the function names available on the object. Aliased as methods

    -
      _.functions = _.methods = function(obj) {
    -    var names = [];
    -    for (var key in obj) {
    -      if (_.isFunction(obj[key])) names.push(key);
    +            
      _.functions = _.methods = function(obj) {
    +    var names = [];
    +    for (var key in obj) {
    +      if (_.isFunction(obj[key])) names.push(key);
         }
    -    return names.sort();
    +    return names.sort();
       };
  • -
  • +
  • - +

    Extend a given object with all the properties in passed-in object(s).

    -
      _.extend = function(obj) {
    -    each(slice.call(arguments, 1), function(source) {
    -      if (source) {
    -        for (var prop in source) {
    +            
      _.extend = function(obj) {
    +    each(slice.call(arguments, 1), function(source) {
    +      if (source) {
    +        for (var prop in source) {
               obj[prop] = source[prop];
             }
           }
         });
    -    return obj;
    +    return obj;
       };
  • -
  • +
  • - +

    Return a copy of the object only containing the whitelisted properties.

    -
      _.pick = function(obj) {
    -    var copy = {};
    -    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    -    each(keys, function(key) {
    -      if (key in obj) copy[key] = obj[key];
    +            
      _.pick = function(obj) {
    +    var copy = {};
    +    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    +    each(keys, function(key) {
    +      if (key in obj) copy[key] = obj[key];
         });
    -    return copy;
    +    return copy;
       };
  • -
  • +
  • - +

    Return a copy of the object without the blacklisted properties.

    -
      _.omit = function(obj) {
    -    var copy = {};
    -    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    -    for (var key in obj) {
    -      if (!_.contains(keys, key)) copy[key] = obj[key];
    +            
      _.omit = function(obj) {
    +    var copy = {};
    +    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    +    for (var key in obj) {
    +      if (!_.contains(keys, key)) copy[key] = obj[key];
         }
    -    return copy;
    +    return copy;
       };
  • -
  • +
  • - +

    Fill in a given object with default properties.

    -
      _.defaults = function(obj) {
    -    each(slice.call(arguments, 1), function(source) {
    -      if (source) {
    -        for (var prop in source) {
    -          if (obj[prop] === void 0) obj[prop] = source[prop];
    +            
      _.defaults = function(obj) {
    +    each(slice.call(arguments, 1), function(source) {
    +      if (source) {
    +        for (var prop in source) {
    +          if (obj[prop] === void 0) obj[prop] = source[prop];
             }
           }
         });
    -    return obj;
    +    return obj;
       };
  • -
  • +
  • - +

    Create a (shallow-cloned) duplicate of an object.

    -
      _.clone = function(obj) {
    -    if (!_.isObject(obj)) return obj;
    -    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
    +            
      _.clone = function(obj) {
    +    if (!_.isObject(obj)) return obj;
    +    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
       };
  • -
  • +
  • - +

    Invokes interceptor with the obj, and then returns obj. -The primary purpose of this method is to "tap into" a method chain, in +The primary purpose of this method is to “tap into” a method chain, in order to perform operations on intermediate results within the chain.

    -
      _.tap = function(obj, interceptor) {
    +            
      _.tap = function(obj, interceptor) {
         interceptor(obj);
    -    return obj;
    +    return obj;
       };
  • -
  • +
  • - +

    Internal recursive comparison function for isEqual.

    -
      var eq = function(a, b, aStack, bStack) {
    +
      var eq = function(a, b, aStack, bStack) {
  • -
  • +
  • - +
    -

    Identical objects are equal. 0 === -0, but they aren't identical. +

    Identical objects are equal. 0 === -0, but they aren’t identical. See the Harmony egal proposal.

    -
        if (a === b) return a !== 0 || 1 / a == 1 / b;
    +
        if (a === b) return a !== 0 || 1 / a == 1 / b;
  • -
  • +
  • - +

    A strict comparison is necessary because null == undefined.

    -
        if (a == null || b == null) return a === b;
    +
        if (a == null || b == null) return a === b;
  • -
  • +
  • - +

    Unwrap any wrapped objects.

    -
        if (a instanceof _) a = a._wrapped;
    -    if (b instanceof _) b = b._wrapped;
    +
        if (a instanceof _) a = a._wrapped;
    +    if (b instanceof _) b = b._wrapped;
  • -
  • +
  • - +

    Compare [[Class]] names.

    -
        var className = toString.call(a);
    -    if (className != toString.call(b)) return false;
    -    switch (className) {
    +
        var className = toString.call(a);
    +    if (className != toString.call(b)) return false;
    +    switch (className) {
  • -
  • +
  • - +

    Strings, numbers, dates, and booleans are compared by value.

    -
          case '[object String]':
    +
          case '[object String]':
  • -
  • +
  • - +

    Primitives and their corresponding object wrappers are equivalent; thus, "5" is equivalent to new String("5").

    -
            return a == String(b);
    -      case '[object Number]':
    +
            return a == String(b);
    +      case '[object Number]':
  • -
  • +
  • - +

    NaNs are equivalent, but non-reflexive. An egal comparison is performed for other numeric values.

    -
            return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
    -      case '[object Date]':
    -      case '[object Boolean]':
    +
            return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
    +      case '[object Date]':
    +      case '[object Boolean]':
  • -
  • +
  • - +

    Coerce dates and booleans to numeric primitive values. Dates are compared by their millisecond representations. Note that invalid dates with millisecond representations @@ -2021,91 +2121,92 @@

    Object Functions

    -
            return +a == +b;
    +
            return +a == +b;
  • -
  • +
  • - +

    RegExps are compared by their source patterns and flags.

    -
          case '[object RegExp]':
    -        return a.source == b.source &&
    +            
          case '[object RegExp]':
    +        return a.source == b.source &&
                    a.global == b.global &&
                    a.multiline == b.multiline &&
                    a.ignoreCase == b.ignoreCase;
         }
    -    if (typeof a != 'object' || typeof b != 'object') return false;
    + if (typeof a != 'object' || typeof b != 'object') return false;
  • -
  • +
  • - +

    Assume equality for cyclic structures. The algorithm for detecting cyclic structures is adapted from ES 5.1 section 15.12.3, abstract operation JO.

    -
        var length = aStack.length;
    -    while (length--) {
    +
        var length = aStack.length;
    +    while (length--) {
  • -
  • +
  • - +

    Linear search. Performance is inversely proportional to the number of unique nested structures.

    -
          if (aStack[length] == a) return bStack[length] == b;
    +            
          if (aStack[length] == a) return bStack[length] == b;
         }
  • -
  • +
  • - +

    Objects with different constructors are not equivalent, but Objects from different frames are.

    -
        var aCtor = a.constructor, bCtor = b.constructor;
    -    if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
    -                             _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
    -      return false;
    +            
        var aCtor = a.constructor, bCtor = b.constructor;
    +    if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
    +                             _.isFunction(bCtor) && (bCtor instanceof bCtor))
    +                        && ('constructor' in a && 'constructor' in b)) {
    +      return false;
         }
  • -
  • +
  • - +

    Add the first object to the stack of traversed objects.

    @@ -2113,31 +2214,31 @@

    Object Functions

        aStack.push(a);
         bStack.push(b);
    -    var size = 0, result = true;
    + var size = 0, result = true;
  • -
  • +
  • - +

    Recursively compare objects and arrays.

    -
        if (className == '[object Array]') {
    +
        if (className == '[object Array]') {
  • -
  • +
  • - +

    Compare array lengths to determine if a deep comparison is necessary.

    @@ -2145,51 +2246,51 @@

    Object Functions

          size = a.length;
           result = size == b.length;
    -      if (result) {
    + if (result) {
  • -
  • +
  • - +

    Deep compare the contents, ignoring non-numeric properties.

    -
            while (size--) {
    -          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
    +            
            while (size--) {
    +          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
             }
           }
    -    } else {
    + } else {
  • -
  • +
  • - +

    Deep compare objects.

    -
          for (var key in a) {
    -        if (_.has(a, key)) {
    +
          for (var key in a) {
    +        if (_.has(a, key)) {
  • -
  • +
  • - +

    Count the expected number of properties.

    @@ -2200,36 +2301,36 @@

    Object Functions

  • -
  • +
  • - +

    Deep compare each member.

    -
              if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
    +            
              if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
             }
           }
  • -
  • +
  • - +

    Ensure that both objects contain the same number of properties.

    -
          if (result) {
    -        for (key in b) {
    -          if (_.has(b, key) && !(size--)) break;
    +            
          if (result) {
    +        for (key in b) {
    +          if (_.has(b, key) && !(size--)) break;
             }
             result = !size;
           }
    @@ -2238,11 +2339,11 @@ 

    Object Functions

  • -
  • +
  • - +

    Remove the first object from the stack of traversed objects.

    @@ -2250,369 +2351,432 @@

    Object Functions

        aStack.pop();
         bStack.pop();
    -    return result;
    +    return result;
       };
  • -
  • +
  • - +

    Perform a deep comparison to check if two objects are equal.

    -
      _.isEqual = function(a, b) {
    -    return eq(a, b, [], []);
    +            
      _.isEqual = function(a, b) {
    +    return eq(a, b, [], []);
       };
  • -
  • +
  • - +

    Is a given array, string, or object empty? -An "empty" object has no enumerable own-properties.

    +An “empty” object has no enumerable own-properties.

    -
      _.isEmpty = function(obj) {
    -    if (obj == null) return true;
    -    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    -    for (var key in obj) if (_.has(obj, key)) return false;
    -    return true;
    +            
      _.isEmpty = function(obj) {
    +    if (obj == null) return true;
    +    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    +    for (var key in obj) if (_.has(obj, key)) return false;
    +    return true;
       };
  • -
  • +
  • - +

    Is a given value a DOM element?

    -
      _.isElement = function(obj) {
    -    return !!(obj && obj.nodeType === 1);
    +            
      _.isElement = function(obj) {
    +    return !!(obj && obj.nodeType === 1);
       };
  • -
  • +
  • - +

    Is a given value an array? -Delegates to ECMA5's native Array.isArray

    +Delegates to ECMA5’s native Array.isArray

    -
      _.isArray = nativeIsArray || function(obj) {
    -    return toString.call(obj) == '[object Array]';
    +            
      _.isArray = nativeIsArray || function(obj) {
    +    return toString.call(obj) == '[object Array]';
       };
  • -
  • +
  • - +

    Is a given variable an object?

    -
      _.isObject = function(obj) {
    -    return obj === Object(obj);
    +            
      _.isObject = function(obj) {
    +    return obj === Object(obj);
       };
  • -
  • +
  • - +

    Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.

    -
      each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
    -    _['is' + name] = function(obj) {
    -      return toString.call(obj) == '[object ' + name + ']';
    +            
      each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
    +    _['is' + name] = function(obj) {
    +      return toString.call(obj) == '[object ' + name + ']';
         };
       });
  • -
  • +
  • - +

    Define a fallback version of the method in browsers (ahem, IE), where -there isn't any inspectable "Arguments" type.

    +there isn’t any inspectable “Arguments” type.

    -
      if (!_.isArguments(arguments)) {
    -    _.isArguments = function(obj) {
    -      return !!(obj && _.has(obj, 'callee'));
    +            
      if (!_.isArguments(arguments)) {
    +    _.isArguments = function(obj) {
    +      return !!(obj && _.has(obj, 'callee'));
         };
       }
  • -
  • +
  • - +

    Optimize isFunction if appropriate.

    -
      if (typeof (/./) !== 'function') {
    -    _.isFunction = function(obj) {
    -      return typeof obj === 'function';
    +            
      if (typeof (/./) !== 'function') {
    +    _.isFunction = function(obj) {
    +      return typeof obj === 'function';
         };
       }
  • -
  • +
  • - +

    Is a given object a finite number?

    -
      _.isFinite = function(obj) {
    -    return isFinite(obj) && !isNaN(parseFloat(obj));
    +            
      _.isFinite = function(obj) {
    +    return isFinite(obj) && !isNaN(parseFloat(obj));
       };
  • -
  • +
  • - +

    Is the given value NaN? (NaN is the only number which does not equal itself).

    -
      _.isNaN = function(obj) {
    -    return _.isNumber(obj) && obj != +obj;
    +            
      _.isNaN = function(obj) {
    +    return _.isNumber(obj) && obj != +obj;
       };
  • -
  • +
  • - +

    Is a given value a boolean?

    -
      _.isBoolean = function(obj) {
    -    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
    +            
      _.isBoolean = function(obj) {
    +    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
       };
  • -
  • +
  • - +

    Is a given value equal to null?

    -
      _.isNull = function(obj) {
    -    return obj === null;
    +            
      _.isNull = function(obj) {
    +    return obj === null;
       };
  • -
  • +
  • - +

    Is a given variable undefined?

    -
      _.isUndefined = function(obj) {
    -    return obj === void 0;
    +            
      _.isUndefined = function(obj) {
    +    return obj === void 0;
       };
  • -
  • +
  • - +

    Shortcut function for checking if an object has a given property directly on itself (in other words, not on a prototype).

    -
      _.has = function(obj, key) {
    -    return hasOwnProperty.call(obj, key);
    +            
      _.has = function(obj, key) {
    +    return hasOwnProperty.call(obj, key);
       };
  • -
  • +
  • -
    - +
    +
    -

    Utility Functions

    +

    Utility Functions

  • -
  • +
  • - + +
    + +
    + +
  • + + +
  • +
    + +
    +

    Run Underscore.js in noConflict mode, returning the _ variable to its previous owner. Returns a reference to the Underscore object.

    -
      _.noConflict = function() {
    +            
      _.noConflict = function() {
         root._ = previousUnderscore;
    -    return this;
    +    return this;
       };
  • -
  • +
  • - +

    Keep the identity function around for default iterators.

    -
      _.identity = function(value) {
    -    return value;
    +            
      _.identity = function(value) {
    +    return value;
    +  };
    +
    +  _.constant = function(value) {
    +    return function () {
    +      return value;
    +    };
    +  };
    +
    +  _.property = function(key) {
    +    return function(obj) {
    +      return obj[key];
    +    };
       };
  • -
  • +
  • - + +
    +

    Returns a predicate for checking whether an object has a given set of key:value pairs.

    + +
    + +
      _.matches = function(attrs) {
    +    return function(obj) {
    +      if (obj === attrs) return true; //avoid comparing an object to itself.
    +      for (var key in attrs) {
    +        if (attrs[key] !== obj[key])
    +          return false;
    +      }
    +      return true;
    +    }
    +  };
    + +
  • + + +
  • +
    + +
    +

    Run a function n times.

    -
      _.times = function(n, iterator, context) {
    -    var accum = Array(Math.max(0, n));
    -    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
    -    return accum;
    +            
      _.times = function(n, iterator, context) {
    +    var accum = Array(Math.max(0, n));
    +    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
    +    return accum;
       };
  • -
  • +
  • - +

    Return a random integer between min and max (inclusive).

    -
      _.random = function(min, max) {
    -    if (max == null) {
    +            
      _.random = function(min, max) {
    +    if (max == null) {
           max = min;
    -      min = 0;
    +      min = 0;
         }
    -    return min + Math.floor(Math.random() * (max - min + 1));
    +    return min + Math.floor(Math.random() * (max - min + 1));
       };
  • -
  • +
  • - + +
    +

    A (possibly faster) way to get the current timestamp as an integer.

    + +
    + +
      _.now = Date.now || function() { return new Date().getTime(); };
    + +
  • + + +
  • +
    + +
    +

    List of HTML entities for escaping.

    -
      var entityMap = {
    -    escape: {
    -      '&': '&amp;',
    -      '<': '&lt;',
    -      '>': '&gt;',
    -      '"': '&quot;',
    -      "'": '&#x27;'
    +            
      var entityMap = {
    +    escape: {
    +      '&': '&amp;',
    +      '<': '&lt;',
    +      '>': '&gt;',
    +      '"': '&quot;',
    +      "'": '&#x27;'
         }
       };
       entityMap.unescape = _.invert(entityMap.escape);
    @@ -2620,39 +2784,39 @@

    Utility Functions

  • -
  • +
  • - +

    Regexes containing the keys and values listed immediately above.

    -
      var entityRegexes = {
    -    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
    -    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
    +            
      var entityRegexes = {
    +    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
    +    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
       };
  • -
  • +
  • - +

    Functions for escaping and unescaping strings to/from HTML interpolation.

    -
      _.each(['escape', 'unescape'], function(method) {
    -    _[method] = function(string) {
    -      if (string == null) return '';
    -      return ('' + string).replace(entityRegexes[method], function(match) {
    -        return entityMap[method][match];
    +            
      _.each(['escape', 'unescape'], function(method) {
    +    _[method] = function(string) {
    +      if (string == null) return '';
    +      return ('' + string).replace(entityRegexes[method], function(match) {
    +        return entityMap[method][match];
           });
         };
       });
    @@ -2660,43 +2824,43 @@

    Utility Functions

  • -
  • +
  • - +

    If the value of the named property is a function then invoke it with the object as context; otherwise, return it.

    -
      _.result = function(object, property) {
    -    if (object == null) return void 0;
    -    var value = object[property];
    -    return _.isFunction(value) ? value.call(object) : value;
    +            
      _.result = function(object, property) {
    +    if (object == null) return void 0;
    +    var value = object[property];
    +    return _.isFunction(value) ? value.call(object) : value;
       };
  • -
  • +
  • - +

    Add your own custom functions to the Underscore object.

    -
      _.mixin = function(obj) {
    -    each(_.functions(obj), function(name) {
    -      var func = _[name] = obj[name];
    -      _.prototype[name] = function() {
    -        var args = [this._wrapped];
    -        push.apply(args, arguments);
    -        return result.call(this, func.apply(_, args));
    +            
      _.mixin = function(obj) {
    +    each(_.functions(obj), function(name) {
    +      var func = _[name] = obj[name];
    +      _.prototype[name] = function() {
    +        var args = [this._wrapped];
    +        push.apply(args, arguments);
    +        return result.call(this, func.apply(_, args));
           };
         });
       };
    @@ -2704,31 +2868,31 @@

    Utility Functions

  • -
  • +
  • - +

    Generate a unique integer id (unique within the entire client session). Useful for temporary DOM ids.

    -
      var idCounter = 0;
    -  _.uniqueId = function(prefix) {
    -    var id = ++idCounter + '';
    -    return prefix ? prefix + id : id;
    +            
      var idCounter = 0;
    +  _.uniqueId = function(prefix) {
    +    var id = ++idCounter + '';
    +    return prefix ? prefix + id : id;
       };
  • -
  • +
  • - +

    By default, Underscore uses ERB-style template delimiters, change the following template settings to use alternative delimiters.

    @@ -2736,232 +2900,244 @@

    Utility Functions

      _.templateSettings = {
    -    evaluate    : /<%([\s\S]+?)%>/g,
    -    interpolate : /<%=([\s\S]+?)%>/g,
    -    escape      : /<%-([\s\S]+?)%>/g
    +    evaluate    : /<%([\s\S]+?)%>/g,
    +    interpolate : /<%=([\s\S]+?)%>/g,
    +    escape      : /<%-([\s\S]+?)%>/g
       };
  • -
  • +
  • - +
    -

    When customizing templateSettings, if you don't want to define an +

    When customizing templateSettings, if you don’t want to define an interpolation, evaluation or escaping regex, we need one that is guaranteed not to match.

    -
      var noMatch = /(.)^/;
    +
      var noMatch = /(.)^/;
  • -
  • +
  • - +

    Certain characters need to be escaped so that they can be put into a string literal.

    -
      var escapes = {
    -    "'":      "'",
    -    '\\':     '\\',
    -    '\r':     'r',
    -    '\n':     'n',
    -    '\t':     't',
    -    '\u2028': 'u2028',
    -    '\u2029': 'u2029'
    +            
      var escapes = {
    +    "'":      "'",
    +    '\\':     '\\',
    +    '\r':     'r',
    +    '\n':     'n',
    +    '\t':     't',
    +    '\u2028': 'u2028',
    +    '\u2029': 'u2029'
       };
     
    -  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
    + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  • -
  • +
  • - +
    -

    JavaScript micro-templating, similar to John Resig's implementation. +

    JavaScript micro-templating, similar to John Resig’s implementation. Underscore templating handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code.

    -
      _.template = function(text, data, settings) {
    -    var render;
    +            
      _.template = function(text, data, settings) {
    +    var render;
         settings = _.defaults({}, settings, _.templateSettings);
  • -
  • +
  • - +

    Combine delimiters into one regular expression via alternation.

    -
        var matcher = new RegExp([
    +            
        var matcher = new RegExp([
           (settings.escape || noMatch).source,
           (settings.interpolate || noMatch).source,
           (settings.evaluate || noMatch).source
    -    ].join('|') + '|$', 'g');
    + ].join('|') + '|$', 'g');
  • -
  • +
  • - +

    Compile the template source, escaping string literals appropriately.

    -
        var index = 0;
    -    var source = "__p+='";
    -    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
    +            
        var index = 0;
    +    var source = "__p+='";
    +    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
           source += text.slice(index, offset)
    -        .replace(escaper, function(match) { return '\\' + escapes[match]; });
    +        .replace(escaper, function(match) { return '\\' + escapes[match]; });
     
    -      if (escape) {
    -        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
    +      if (escape) {
    +        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
           }
    -      if (interpolate) {
    -        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
    +      if (interpolate) {
    +        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
           }
    -      if (evaluate) {
    -        source += "';\n" + evaluate + "\n__p+='";
    +      if (evaluate) {
    +        source += "';\n" + evaluate + "\n__p+='";
           }
           index = offset + match.length;
    -      return match;
    +      return match;
         });
    -    source += "';\n";
    + source += "';\n";
  • -
  • +
  • - +

    If a variable is not specified, place data values in local scope.

    -
        if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
    +            
        if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
     
    -    source = "var __t,__p='',__j=Array.prototype.join," +
    -      "print=function(){__p+=__j.call(arguments,'');};\n" +
    -      source + "return __p;\n";
    +    source = "var __t,__p='',__j=Array.prototype.join," +
    +      "print=function(){__p+=__j.call(arguments,'');};\n" +
    +      source + "return __p;\n";
     
    -    try {
    -      render = new Function(settings.variable || 'obj', '_', source);
    -    } catch (e) {
    +    try {
    +      render = new Function(settings.variable || 'obj', '_', source);
    +    } catch (e) {
           e.source = source;
    -      throw e;
    +      throw e;
         }
     
    -    if (data) return render(data, _);
    -    var template = function(data) {
    -      return render.call(this, data, _);
    +    if (data) return render(data, _);
    +    var template = function(data) {
    +      return render.call(this, data, _);
         };
  • -
  • +
  • - +

    Provide the compiled function source as a convenience for precompilation.

    -
        template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
    +            
        template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
     
    -    return template;
    +    return template;
       };
  • -
  • +
  • - +
    -

    Add a "chain" function, which will delegate to the wrapper.

    +

    Add a “chain” function, which will delegate to the wrapper.

    -
      _.chain = function(obj) {
    -    return _(obj).chain();
    +            
      _.chain = function(obj) {
    +    return _(obj).chain();
       };
  • -
  • +
  • -
    - +
    +
    -

    OOP

    +

    OOP

  • -
  • +
  • - +

    If Underscore is called as a function, it returns a wrapped object that can be used OO-style. This wrapper holds altered versions of all the underscore functions. Wrapped objects may be chained.

    -

    Helper function to continue chaining intermediate results.

    -
      var result = function(obj) {
    -    return this._chain ? _(obj).chain() : obj;
    +        
  • + + +
  • +
    + +
    + +
    +

    Helper function to continue chaining intermediate results.

    + +
    + +
      var result = function(obj) {
    +    return this._chain ? _(obj).chain() : obj;
       };
  • -
  • +
  • - +

    Add all of the Underscore functions to the wrapper object.

    @@ -2972,43 +3148,43 @@

    OOP

  • -
  • +
  • - +

    Add all mutator Array functions to the wrapper.

    -
      each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    -    var method = ArrayProto[name];
    -    _.prototype[name] = function() {
    -      var obj = this._wrapped;
    -      method.apply(obj, arguments);
    -      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
    -      return result.call(this, obj);
    +            
      each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    +    var method = ArrayProto[name];
    +    _.prototype[name] = function() {
    +      var obj = this._wrapped;
    +      method.apply(obj, arguments);
    +      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
    +      return result.call(this, obj);
         };
       });
  • -
  • +
  • - +

    Add all accessor Array functions to the wrapper.

    -
      each(['concat', 'join', 'slice'], function(name) {
    -    var method = ArrayProto[name];
    -    _.prototype[name] = function() {
    -      return result.call(this, method.apply(this._wrapped, arguments));
    +            
      each(['concat', 'join', 'slice'], function(name) {
    +    var method = ArrayProto[name];
    +    _.prototype[name] = function() {
    +      return result.call(this, method.apply(this._wrapped, arguments));
         };
       });
     
    @@ -3017,41 +3193,65 @@ 

    OOP

  • -
  • +
  • - +

    Start chaining a wrapped Underscore object.

    -
        chain: function() {
    -      this._chain = true;
    -      return this;
    +            
        chain: function() {
    +      this._chain = true;
    +      return this;
         },
  • -
  • +
  • - +

    Extracts the result from a wrapped and chained object.

    -
        value: function() {
    -      return this._wrapped;
    +            
        value: function() {
    +      return this._wrapped;
         }
     
    -  });
    +  });
    + +
  • + + +
  • +
    + +
    + +
    +

    AMD registration happens at the end for compatibility with AMD loaders +that may not enforce next-turn semantics on modules. Even though general +practice for AMD registration is to be anonymous, underscore registers +as a named module because, like jQuery, it is a base library that is +popular enough to be bundled in a third party lib, but not be part of +an AMD load request. Those cases could generate an error when an +anonymous define() is called outside of a loader request.

    -}).call(this);
    + + +
      if (typeof define === 'function' && define.amd) {
    +    define('underscore', [], function() {
    +      return _;
    +    });
    +  }
    +}).call(this);
  • diff --git a/index.html b/index.html index 3ba65a60d..163cc76f6 100644 --- a/index.html +++ b/index.html @@ -181,7 +181,7 @@