(function() {
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 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() {
Establish the root object, window
in the browser, or exports
on the server.
var root = this;
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;
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._;
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 = {};
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
-
+
- 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;
-
+
- 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._ = _;
}
-
+
- _.VERSION = '1.5.2';
+ _.VERSION = '1.6.0';
-
+
-
-
+
+
+
+
+
+
+
+
+
+ ¶
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;
};
-
+
- _.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;
};
-
+
- _.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;
};
-
+
- _.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 = 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);
});
};
-
+
- _.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;
};
-
+
- _.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));
};
-
+
- 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;
};
-
+
- _.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);
};
-
+
- _.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;
};
-
+
-
-
+
+
+
+
+
+
+
+
+
+ ¶
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);
};
-
+
- _.compact = function(array) {
- return _.filter(array, _.identity);
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
};
-
+
- 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 = function(array, shallow) {
- return flatten(array, shallow, []);
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, []);
};
-
+
- _.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));
};
-
+
- _.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;
};
-
+
-
-
+
+
+
+
+
+
+
+
+
+ ¶
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 = 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);
};
-
+
- _.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];
};
};
-
+
- _.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
-
+
-
-
+
+
+
+
+
+
+
+
+
+ ¶
- 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;
};
-
+
- _.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 = 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;
};
-
+
- _.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 = 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;
};
-
+
- _.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;
};
-
+
- _.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;
};
-
+
- _.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;
};
-
+
- _.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;
};
-
+
- 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;
-
+
- if (a == null || b == null) return a === b;
+ if (a == null || b == null) return a === b;
-
+
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
-
+
- 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) {
-
+
- 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]':
-
+
NaN
s 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;
-
+
- 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 Object
s
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;
}
-
+
-
+
- if (className == '[object Array]') {
+ if (className == '[object Array]') {
-
+
-
+
- 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 {
-
+
- 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
-
+
- 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;
}
}
-
+
- 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;
};
-
+
- _.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;
};
-
+
- _.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
-