diff --git a/README.md b/README.md
index 8dbee11005..cd0b26894d 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,14 @@
-# Lo-Dash v0.6.1
+# Lo-Dash v0.7.0
-A drop-in replacement[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer) for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues-30), and [additional features](https://github.com/bestiejs/lodash#features).
+A drop-in replacement[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer) for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues-20), and [additional features](https://github.com/bestiejs/lodash#features).
Lo-Dash’s performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
## Download
- * [Development source](https://raw.github.com/bestiejs/lodash/v0.6.1/lodash.js)
- * [Production source](https://raw.github.com/bestiejs/lodash/v0.6.1/lodash.min.js)
- * CDN copies of ≤ [v0.6.1](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.6.1/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
+ * [Development source](https://raw.github.com/bestiejs/lodash/v0.7.0/lodash.js)
+ * [Production source](https://raw.github.com/bestiejs/lodash/v0.7.0/lodash.min.js)
+ * CDN copies of ≤ [v0.7.0](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.7.0/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
* For optimal performance, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
## Dive in
@@ -27,6 +27,7 @@ For more information check out these screencasts over Lo-Dash:
* [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
* [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
* [Unit testing in Lo-Dash](https://vimeo.com/45865290)
+ * [Lo-Dash’s approach to native method use](https://vimeo.com/48576012)
## Features
@@ -35,22 +36,24 @@ For more information check out these screencasts over Lo-Dash:
* [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning
* [_.countBy](http://lodash.com/docs#countBy) as a companion function for [_.groupBy](http://lodash.com/docs#groupBy) and [_.sortBy](http://lodash.com/docs#sortBy)
* [_.debounce](http://lodash.com/docs#debounce)’ed functions match [_.throttle](http://lodash.com/docs#throttle)’ed functions’ return value behavior
- * [_.drop](http://lodash.com/docs#drop) for the inverse functionality of [_.pick](http://lodash.com/docs#pick)
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties
- * [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
* [_.indexOf](http://lodash.com/docs#indexOf) and [_.lastIndexOf](http://lodash.com/docs#lastIndexOf) accept a `fromIndex` argument
+ * [_.invert](http://lodash.com/docs#invert) to create inverted objects
* [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend)
+ * [_.object](http://lodash.com/docs#object) and [_.pairs](http://lodash.com/docs#pairs) for composing objects
+ * [_.omit](http://lodash.com/docs#omit) for the inverse functionality of [_.pick](http://lodash.com/docs#pick)
* [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding
- * [_.pick](http://lodash.com/docs#pick) and [_.drop](http://lodash.com/docs#drop) accept `callback` and `thisArg` arguments
+ * [_.pick](http://lodash.com/docs#pick) and [_.omit](http://lodash.com/docs#omit) accept `callback` and `thisArg` arguments
+ * [_.random](http://lodash.com/docs#random) for generating random numbers within a given range
* [_.sortBy](http://lodash.com/docs#sortBy) performs a [stable](http://en.wikipedia.org/wiki/Sorting_algorithm#Stability) sort
* [_.template](http://lodash.com/docs#template) utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging
* [_.unescape](http://lodash.com/docs#unescape) to unescape strings escaped by [_.escape](http://lodash.com/docs#escape)
* [_.where](http://lodash.com/docs#where) for filtering collections by contained properties
- * [_.zipObject](http://lodash.com/docs#zipObject) for composing objects
+ * [_.countBy](http://lodash.com/docs#countBy), [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
- [and more…](http://lodash.com/docs "_.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _sortBy") accept strings
+ [and more…](http://lodash.com/docs "_.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _.sortBy, _.where") accept strings
## Support
@@ -59,9 +62,9 @@ Lo-Dash has been tested in at least Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.2
## Custom builds
Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
-We handle all the method dependency and alias mapping for you.
+To top it off, we handle all method dependency and alias mapping for you.
- * Backbone builds, containing all methods required by Backbone, may be created using the `backbone` modifier argument.
+ * Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.
```bash
lodash backbone
```
@@ -86,39 +89,59 @@ lodash mobile
lodash strict
```
- * Underscore builds, containing only methods included in Underscore, may be created using the `underscore` modifier argument.
+ * Underscore builds, with iteration fixes removed and only Underscore’s API, may be created using the `underscore` modifier argument.
```bash
lodash underscore
```
-Custom builds may be created in three ways:
+Custom builds may be created using the following commands:
- 1. Use the `category` argument to pass the categories of methods to include in the build.
+ * Use the `category` argument to pass comma separated categories of methods to include in the build.
Valid categories are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
```bash
lodash category=collections,functions
lodash category="collections, functions"
```
- 2. Use the `exclude` argument to pass the names of methods to exclude from the build.
+ * Use the `exclude` argument to pass comma separated names of methods to exclude from the build.
```bash
lodash exclude=union,uniq,zip
lodash exclude="union, uniq, zip"
```
- 3. Use the `include` argument to pass the names of methods to include in the build.
+ * Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.
+ Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
+```bash
+lodash exports=amd,commonjs,node
+lodash include="amd, commonjs, node"
+```
+
+ * Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
+```bash
+lodash iife="!function(window,undefined){%output%}(this)"
+```
+
+ * Use the `include` argument to pass comma separated names of methods to include in the build.
```bash
lodash include=each,filter,map
lodash include="each, filter, map"
```
-All arguments, except `backbone` with `underscore`, `exclude` with `include`, and `legacy` with `csp`/`mobile`, may be combined.
+All arguments, except `exclude` with `include` and `legacy` with `csp`/`mobile`, may be combined.
```bash
-lodash backbone legacy category=utilities exclude=first,last
-lodash underscore mobile strict category=functions include=pick,uniq
+lodash backbone legacy exports=global category=utilities exclude=first,last
+lodash -s underscore mobile strict exports=amd category=functions include=pick,uniq
```
+The following options are also supported:
+
+ * `-c`, `--stdout` Write output to standard output
+ * `-h`, `--help` Display help information
+ * `-o`, `--output` Write output to a given path/filename
+ * `-s`, `--silent` Skip status updates normally logged to the console
+ * `-V`, `--version` Output current version of Lo-Dash
+
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
Custom builds are saved to `lodash.custom.js` and `lodash.custom.min.js`.
@@ -169,40 +192,33 @@ require({
});
```
-## Resolved Underscore.js issues (30+)
-
- * Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L578-584)]
- * Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L526-536)]
- * Ensure *“Arrays”*, “Collections”, and “Objects” methods don’t error when passed falsey arguments [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1668-1703)]
- * Ensure *“Collections”* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L538-555)]
- * Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1383-1386)]
- * Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L589-614)]
- * Handle arrays with `undefined` values correctly in IE < 9 [[#601](https://github.com/documentcloud/underscore/issues/601)]
- * Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L117-123)]
- * Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L101-115)]
- * `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L135-138)]
- * `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L205-220)]
- * `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L275-284)]
- * `_.countBy` and `_.groupBy` should only add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L292-299)]
- * `_.escape` should return an empty string when passed `null` or `undefined` [[#427](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L402-405)]
- * `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [#718](https://github.com/documentcloud/underscore/issues/718), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L979-1001)]
- * `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L521-524)]
- * `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L616-635)]
- * `_.isElement` should use strict equality for its duck type check [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L731-740)]
- * `_.isEmpty` and `_.size` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L767-772)]
- * `_.isEqual` should return `true` for like-objects from different documents [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L808-828)]
- * `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L836-848)]
- * `_.isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L856-858)]
- * `_.keys` and `_.size` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L912-914)]
- * `_.once` should free the given function for garbage collection [[#693](https://github.com/documentcloud/underscore/pull/693)]
- * `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1170-1173)]
- * `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1205-1219)]
- * `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1263-1265)]
- * `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1353-1362)]
- * `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1377-1381)]
- * `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1473-1483)]
- * `_.toArray` uses custom `toArray` methods of arrays and strings [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1510-1518)]
- * `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.6.1/test/test.js#L1630-1632)]
+## Resolved Underscore.js issues (20+)
+
+ * Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L543-549)]
+ * Ensure array-like objects with invalid `length` properties are treated like regular objects [[#741](https://github.com/documentcloud/underscore/issues/741), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L491-501)]
+ * Ensure *“Arrays”*, *“Collections”*, and *“Objects”* methods don’t error when passed falsey arguments [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1719-1754)]
+ * Ensure *“Collections”* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L503-520)]
+ * Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L554-579)]
+ * Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L134-140)]
+ * Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L118-132)]
+ * `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L223-234)]
+ * `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L289-298)]
+ * `_.countBy` and `_.groupBy` should only add values to own, not inherited, properties [[#736](https://github.com/documentcloud/underscore/issues/736), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L306-313)]
+ * `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [#718](https://github.com/documentcloud/underscore/issues/718), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L946-968)]
+ * `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L486-489)]
+ * `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L581-600)]
+ * `_.isElement` should use strict equality for its duck type check [[#734](https://github.com/documentcloud/underscore/issues/734), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L696-705)]
+ * `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L732-737)]
+ * `_.isEqual` should return `true` for like-objects from different documents [[#733](https://github.com/documentcloud/underscore/issues/733), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L784-795)]
+ * `_.isEqual` should use custom `isEqual` methods before checking strict equality [[#748](https://github.com/documentcloud/underscore/issues/748), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L758-761)]
+ * `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L803-815)]
+ * `_.isNaN(new Number(NaN))` should return `true` [[#749](https://github.com/documentcloud/underscore/issues/749), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L823-825)]
+ * `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L879-881)]
+ * `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1222-1225)]
+ * `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1257-1271)]
+ * `_.sortedIndex` should support arrays with high `length` values [[#735](https://github.com/documentcloud/underscore/issues/735), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1404-1413)]
+ * `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1534-1544)]
+ * `_.toArray` uses custom `toArray` methods of arrays and strings [[#747](https://github.com/documentcloud/underscore/issues/747), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1571-1579)]
## Optimized methods (50+)
@@ -214,9 +230,7 @@ require({
* `_.defaults`
* `_.defer`
* `_.difference`
- * `_.drop`, `_.omit`
* `_.each`
- * `_.escape`
* `_.every`, `_.all`
* `_.extend`
* `_.filter`, `_.select`
@@ -227,6 +241,7 @@ require({
* `_.groupBy`
* `_.indexOf`
* `_.intersection`
+ * `_.invert`
* `_.invoke`
* `_.isArguments`
* `_.isDate`
@@ -244,6 +259,8 @@ require({
* `_.memoize`
* `_.min`
* `_.mixin`
+ * `_.omit`
+ * `_.pairs`
* `_.pick`
* `_.pluck`
* `_.reduce`, `_.foldl`, `_.inject`
@@ -267,21 +284,30 @@ require({
## Release Notes
-### v0.6.1
-
- * Ensured IE conditional compilation isn’t enabled by the `useSourceURL` test
- * Optimized `isPlainObject`
-
-### v0.6.0
-
- * Added `callback` and `thisArg` arguments to `_.drop` and `_.pick`
- * Added `hasObjectSpliceBug` test to avoid `delete` operator use
- * Added `_.omit` alias for `_.drop`
- * Added [_.unescape](http://lodash.com/docs#unescape)
- * Ensured `_.reduce` works with string objects in IE < 9
- * Made compiled methods take advantage of engines with strict mode optimizations
- * Optimized `_.intersection` and removed its dependency on `_.every`
- * Reduced the file size of the `underscore` build
+### v0.7.0
+
+#### Compatibility Warnings ####
+
+ * Renamed `_.zipObject` to `_.object`
+ * Replaced `_.drop` with `_.omit`
+ * Made `_.drop` alias `_.rest`
+
+#### Changes ####
+
+ * Added [_.invert](http://lodash.com/docs#invert), [_.pairs](http://lodash.com/docs#pairs), and [_.random](http://lodash.com/docs#random)
+ * Added `_.result` to the `backbone` build
+ * Added `exports`, `iife`, `-c`/`--stdout`, `-o`/`--output`, and `-s`/`--silent` build options
+ * Ensured `isPlainObject` works with objects from other documements
+ * Ensured `_.isEqual` compares values with circular references correctly
+ * Ensured `_.merge` work with four or more arguments
+ * Ensured `_.sortBy` performs a stable sort for `undefined` values
+ * Ensured `_.template` works with "interpolate" delimiters containing ternary operators
+ * Ensured the production build works in Node.js
+ * Ensured template delimiters are tokenized correctly
+ * Made pseudo private properties `_chain` and `_wrapped` double-underscored to avoid conflicts
+ * Made `minify.js` support `underscore.js`
+ * Reduced the size of `mobile` and `underscore` builds
+ * Simplified `_.isEqual` and `_.size`
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
diff --git a/build.js b/build.js
index 9f1156841c..d412e73e8e 100755
--- a/build.js
+++ b/build.js
@@ -2,78 +2,21 @@
;(function() {
'use strict';
- /** The debug version of `source` */
- var debugSource;
-
/** Load modules */
var fs = require('fs'),
path = require('path'),
vm = require('vm'),
- minify = require(path.join(__dirname, 'build', 'minify'));
+ minify = require(path.join(__dirname, 'build', 'minify')),
+ _ = require(path.join(__dirname, 'lodash'));
/** The current working directory */
var cwd = process.cwd();
- /** Flag used to specify a Backbone build */
- var isBackbone = process.argv.indexOf('backbone') > -1;
-
- /** Flag used to specify a Content Security Policy build */
- var isCSP = process.argv.indexOf('csp') > -1 || process.argv.indexOf('CSP') > -1;
-
- /** Flag used to specify a legacy build */
- var isLegacy = process.argv.indexOf('legacy') > -1;
-
- /** Flag used to specify an Underscore build */
- var isUnderscore = process.argv.indexOf('underscore') > -1;
-
- /** Flag used to specify a mobile build */
- var isMobile = !isLegacy && (isCSP || isUnderscore || process.argv.indexOf('mobile') > -1);
-
- /**
- * Flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
- * constructed using the "use strict" directive.
- */
- var isStrict = process.argv.indexOf('strict') > -1;
-
- /** Flag used to specify if the build should include the "use strict" directive */
- var useStrict = isStrict || !(isLegacy || isMobile);
-
/** Shortcut used to convert array-like objects to arrays */
var slice = [].slice;
- /** The lodash.js source */
- var source = fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8');
-
- /** Load customized Lo-Dash module */
- var lodash = (function() {
- var sandbox = {};
-
- if (isStrict) {
- source = setUseStrictOption(source, true);
- } else {
- source = removeUseStrictDirective(source);
- if (!useStrict) {
- source = setUseStrictOption(source, false);
- }
- }
- if (isLegacy) {
- source = replaceVar(source, 'noArgsClass', 'true');
- ['isBindFast', 'isKeysFast', 'isStrictFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
- source = replaceVar(source, varName, 'false');
- });
- }
- else if (isUnderscore) {
- // remove `prototype` [[Enumerable]] fix from `iteratorTemplate`
- source = source
- .replace(/(?: *\/\/.*\n)*\s*' *(?:<% *)?if *\(!hasDontEnumBug *(?:&&|\))[\s\S]+?<% *} *(?:%>|').+/g, '')
- .replace(/!hasDontEnumBug *\|\|/g, '');
- }
- if (isMobile) {
- source = replaceVar(source, 'isKeysFast', 'false');
- }
- vm.runInNewContext(source, sandbox);
- return sandbox._;
- }());
+ /** Shortcut to the `stdout` object */
+ var stdout = process.stdout;
/** Used to associate aliases with their real names */
var aliasToRealMap = {
@@ -81,6 +24,7 @@
'any': 'some',
'collect': 'map',
'detect': 'find',
+ 'drop': 'rest',
'each': 'forEach',
'foldl': 'reduce',
'foldr': 'reduceRight',
@@ -88,7 +32,6 @@
'include': 'contains',
'inject': 'reduce',
'methods': 'functions',
- 'omit': 'drop',
'select': 'filter',
'tail': 'rest',
'take': 'first',
@@ -98,7 +41,6 @@
/** Used to associate real names with their aliases */
var realToAliasMap = {
'contains': ['include'],
- 'drop': ['omit'],
'every': ['all'],
'filter': ['select'],
'find': ['detect'],
@@ -108,56 +50,11 @@
'map': ['collect'],
'reduce': ['foldl', 'inject'],
'reduceRight': ['foldr'],
- 'rest': ['tail'],
+ 'rest': ['drop', 'tail'],
'some': ['any'],
'uniq': ['unique']
};
- /** Used to track Backbone's Lo-Dash dependencies */
- var backboneDependencies = [
- 'bind',
- 'bindAll',
- 'clone',
- 'contains',
- 'escape',
- 'every',
- 'extend',
- 'filter',
- 'find',
- 'first',
- 'forEach',
- 'groupBy',
- 'has',
- 'indexOf',
- 'initial',
- 'invoke',
- 'isArray',
- 'isEmpty',
- 'isEqual',
- 'isFunction',
- 'isObject',
- 'isRegExp',
- 'keys',
- 'last',
- 'lastIndexOf',
- 'map',
- 'max',
- 'min',
- 'mixin',
- 'reduce',
- 'reduceRight',
- 'reject',
- 'rest',
- 'shuffle',
- 'size',
- 'some',
- 'sortBy',
- 'sortedIndex',
- 'toArray',
- 'uniqueId',
- 'without'
- ];
-
/** Used to track function dependencies */
var dependencyMap = {
'after': [],
@@ -174,7 +71,6 @@
'defer': [],
'delay': [],
'difference': ['indexOf'],
- 'drop': ['indexOf', 'isArguments'],
'escape': [],
'every': ['identity'],
'extend': ['isArguments'],
@@ -192,6 +88,7 @@
'indexOf': ['sortedIndex'],
'initial': [],
'intersection': ['indexOf'],
+ 'invert': [],
'invoke': [],
'isArguments': [],
'isArray': [],
@@ -219,10 +116,14 @@
'min': [],
'mixin': ['forEach', 'functions'],
'noConflict': [],
+ 'object': [],
+ 'omit': ['indexOf', 'isArguments'],
'once': [],
+ 'pairs': [],
'partial': [],
'pick': [],
'pluck': [],
+ 'random': [],
'range': [],
'reduce': [],
'reduceRight': ['keys'],
@@ -230,11 +131,11 @@
'rest': [],
'result': ['isFunction'],
'shuffle': [],
- 'size': ['isArguments', 'isFunction', 'keys'],
+ 'size': ['keys'],
'some': ['identity'],
'sortBy': [],
'sortedIndex': ['bind'],
- 'tap': [],
+ 'tap': ['mixin'],
'template': ['escape'],
'throttle': [],
'times': [],
@@ -243,15 +144,15 @@
'union': ['indexOf'],
'uniq': ['identity', 'indexOf'],
'uniqueId': [],
+ 'value': ['mixin'],
'values': ['isArguments'],
'where': ['forIn'],
'without': ['indexOf'],
'wrap': [],
- 'zip': ['max', 'pluck'],
- 'zipObject': []
+ 'zip': ['max', 'pluck']
};
- /** Used to `iteratorTemplate` */
+ /** Used to inline `iteratorTemplate` */
var iteratorOptions = [
'args',
'array',
@@ -274,48 +175,102 @@
'useStrict'
];
- /** Collections of method names */
- var excludeMethods = [],
- includeMethods = [],
- allMethods = Object.keys(dependencyMap);
+ /** List of all Lo-Dash methods */
+ var allMethods = _.keys(dependencyMap);
- var underscoreMethods = lodash.without.apply(lodash, [allMethods].concat([
+ /** List Backbone's Lo-Dash dependencies */
+ var backboneDependencies = [
+ 'bind',
+ 'bindAll',
+ 'clone',
+ 'contains',
+ 'escape',
+ 'every',
+ 'extend',
+ 'filter',
+ 'find',
+ 'first',
+ 'forEach',
+ 'groupBy',
+ 'has',
+ 'indexOf',
+ 'initial',
+ 'invoke',
+ 'isArray',
+ 'isEmpty',
+ 'isEqual',
+ 'isFunction',
+ 'isObject',
+ 'isRegExp',
+ 'keys',
+ 'last',
+ 'lastIndexOf',
+ 'map',
+ 'max',
+ 'min',
+ 'mixin',
+ 'reduce',
+ 'reduceRight',
+ 'reject',
+ 'rest',
+ 'result',
+ 'shuffle',
+ 'size',
+ 'some',
+ 'sortBy',
+ 'sortedIndex',
+ 'toArray',
+ 'uniqueId',
+ 'without'
+ ];
+
+ /** List of methods used by Underscore */
+ var underscoreMethods = _.without.apply(_, [allMethods].concat([
'countBy',
- 'drop',
'forIn',
'forOwn',
+ 'invert',
'merge',
+ 'object',
+ 'omit',
+ 'pairs',
'partial',
+ 'random',
'unescape',
- 'where',
- 'zipObject'
+ 'where'
]));
- /** Used to specify whether filtering is for exclusion or inclusion */
- var filterType = process.argv.reduce(function(result, value) {
- if (result) {
- return result;
- }
- var pair = value.match(/^(exclude|include)=(.*)$/);
- if (!pair) {
- return result;
- }
- // remove nonexistent method names
- var methodNames = lodash.intersection(allMethods, pair[2].split(/, */).map(getRealName));
-
- if (pair[1] == 'exclude') {
- excludeMethods = methodNames;
- } else {
- includeMethods = methodNames;
- }
- // return `filterType`
- return pair[1];
- }, '');
+ /** List of ways to export the `LoDash` function */
+ var exportsAll = [
+ 'amd',
+ 'commonjs',
+ 'global',
+ 'node'
+ ];
/*--------------------------------------------------------------------------*/
/**
- * Logs the help message to the console.
+ * Removes unnecessary comments, whitespace, and pseudo private properties.
+ *
+ * @private
+ * @param {String} source The source to process.
+ * @returns {String} Returns the modified source.
+ */
+ function cleanupSource(source) {
+ return source
+ // remove pseudo private properties
+ .replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n')
+ // remove lines with just whitespace and semicolons
+ .replace(/^ *;\n/gm, '')
+ // consolidate consecutive horizontal rule comment separators
+ .replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
+ return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
+ });
+ }
+
+ /**
+ * Writes the help message to standard output.
*
* @private
*/
@@ -324,22 +279,30 @@
'',
' Commands:',
'',
- ' lodash backbone Build containing all methods required by Backbone',
+ ' lodash backbone Build with only methods required by Backbone',
' lodash csp Build supporting default Content Security Policy restrictions',
' lodash legacy Build tailored for older browsers without ES5 support',
- ' lodash mobile Build with IE < 9 bug fixes and method compilation removed',
- ' lodash strict Build with `_.bindAll`, `_.defaults`, and `_.extend` in strict mode',
- ' lodash underscore Build containing only methods included in Underscore',
- ' lodash category=... Comma separated categories of methods to include in the build',
+ ' lodash mobile Build with IE < 9 bug fixes & method compilation removed',
+ ' lodash strict Build with `_.bindAll`, `_.defaults`, & `_.extend` in strict mode',
+ ' lodash underscore Build with iteration fixes removed and only Underscore’s API',
' lodash exclude=... Comma separated names of methods to exclude from the build',
' lodash include=... Comma separated names of methods to include in the build',
+ ' lodash category=... Comma separated categories of methods to include in the build',
+ ' (i.e. “arrays”, “chaining”, “collections”, “functions”, “objects”, and “utilities”)',
+ ' lodash exports=... Comma separated names of ways to export the `LoDash` function',
+ ' (i.e. “amd”, “commonjs”, “global”, “node”, and “none”)',
+ ' lodash iife=... Code to replace the immediately-invoked function expression that wraps Lo-Dash',
+ ' (e.g. “!function(window,undefined){%output%}(this)”)',
'',
- ' All arguments, except `backbone` with `underscore`, `exclude` with `include`,',
- ' and `legacy` with `csp`/`mobile`, may be combined.',
+ ' All arguments, except `exclude` with `include` & `legacy` with `csp`/`mobile`,',
+ ' may be combined.',
'',
' Options:',
'',
+ ' -c, --stdout Write output to standard output',
' -h, --help Display help information',
+ ' -o, --output Write output to a given path/filename',
+ ' -s, --silent Skip status updates normally logged to the console',
' -V, --version Output current version of Lo-Dash',
''
].join('\n'));
@@ -349,11 +312,11 @@
* Gets the aliases associated with a given function name.
*
* @private
- * @param {String} funcName The name of the function to get aliases for.
+ * @param {String} methodName The name of the method to get aliases for.
* @returns {Array} Returns an array of aliases.
*/
- function getAliases(funcName) {
- return realToAliasMap[funcName] || [];
+ function getAliases(methodName) {
+ return realToAliasMap[methodName] || [];
}
/**
@@ -368,17 +331,17 @@
}
/**
- * Gets an array of depenants for a function by a given name.
+ * Gets an array of depenants for a method by a given name.
*
* @private
- * @param {String} funcName The name of the function to query.
- * @returns {Array} Returns an array of function dependants.
+ * @param {String} methodName The name of the method to query.
+ * @returns {Array} Returns an array of method dependants.
*/
- function getDependants(funcName) {
- // iterate over `dependencyMap`, adding the names of functions that
- // have `funcName` as a dependency
- return lodash.reduce(dependencyMap, function(result, dependencies, otherName) {
- if (lodash.contains(dependencies, funcName)) {
+ function getDependants(methodName) {
+ // iterate over the `dependencyMap`, adding the names of methods that
+ // have `methodName` as a dependency
+ return _.reduce(dependencyMap, function(result, dependencies, otherName) {
+ if (_.contains(dependencies, methodName)) {
result.push(otherName);
}
return result;
@@ -386,23 +349,23 @@
}
/**
- * Gets an array of dependencies for a given function name. If passed an array
+ * Gets an array of dependencies for a given method name. If passed an array
* of dependencies it will return an array containing the given dependencies
* plus any additional detected sub-dependencies.
*
* @private
- * @param {Array|String} funcName A single function name or array of
+ * @param {Array|String} methodName A single method name or array of
* dependencies to query.
- * @returns {Array} Returns an array of function dependencies.
+ * @returns {Array} Returns an array of method dependencies.
*/
- function getDependencies(funcName) {
- var dependencies = Array.isArray(funcName) ? funcName : dependencyMap[funcName];
+ function getDependencies(methodName) {
+ var dependencies = Array.isArray(methodName) ? methodName : dependencyMap[methodName];
if (!dependencies) {
return [];
}
- // recursively accumulate the dependencies of the `funcName` function, and
+ // recursively accumulate the dependencies of the `methodName` function, and
// the dependencies of its dependencies, and so on.
- return lodash.uniq(dependencies.reduce(function(result, otherName) {
+ return _.uniq(dependencies.reduce(function(result, otherName) {
result.push.apply(result, getDependencies(otherName).concat(otherName));
return result;
}, []));
@@ -418,7 +381,7 @@
function getFunctionSource(func) {
var source = func.source || (func + '');
- // all leading whitespace
+ // format leading whitespace
return source.replace(/\n(?:.*)/g, function(match, index) {
match = match.slice(1);
return (
@@ -439,14 +402,14 @@
}
/**
- * Gets the real name, not alias, of a given function name.
+ * Gets the real name, not alias, of a given method name.
*
* @private
- * @param {String} funcName The name of the function to resolve.
- * @returns {String} Returns the real name.
+ * @param {String} methodName The name of the method to resolve.
+ * @returns {String} Returns the real method name.
*/
- function getRealName(funcName) {
- return aliasToRealMap[funcName] || funcName;
+ function getRealName(methodName) {
+ return aliasToRealMap[methodName] || methodName;
}
/**
@@ -566,17 +529,6 @@
return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/, '');
}
- /**
- * Removes the `isPlainObject` fallback from `source`.
- *
- * @private
- * @param {String} source The source to process.
- * @returns {String} Returns the source with the `isPlainObject` fallback removed.
- */
- function removeIsPlainObjectFallback(source) {
- return source.replace(/(?:\s*\/\/.*)*\n( +)if *\(!isPlainObject[\s\S]+?};\n\1}/, '');
- }
-
/**
* Removes the `Object.keys` object iteration optimization from `source`.
*
@@ -587,10 +539,10 @@
function removeKeysOptimization(source) {
return removeVar(source, 'isKeysFast')
// remove optimized branch in `iteratorTemplate`
- .replace(/(?: *\/\/.*\n)*\s*'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2')
+ .replace(/(?: *\/\/.*\n)* *'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2')
// remove `isKeysFast` from `beforeLoop.object` of `mapIteratorOptions`
.replace(/=\s*'\s*\+\s*\(isKeysFast.+/, "= []'")
- // remove `isKeysFast` from `inLoop.object` of `mapIteratorOptions`, `invoke`, `pluck`, and `sortBy`
+ // remove `isKeysFast` from `inLoop.object` of `mapIteratorOptions`, `invoke`, `pairs`, `pluck`, and `sortBy`
.replace(/'\s*\+\s*\(isKeysFast[^)]+?\)\s*\+\s*'/g, '.push')
// remove data object property assignment in `createIterator`
.replace(/\s*.+?\.isKeysFast *=.+/, '');
@@ -605,7 +557,7 @@
*/
function removeNoArgsClass(source) {
return removeVar(source, 'noArgsClass')
- // remove `noArgsClass` from `_.clone`, `_.isEqual`, and `_.size`
+ // remove `noArgsClass` from `_.clone` and `_.isEqual`
.replace(/ *\|\| *\(noArgsClass *&&[^)]+?\)\)/g, '')
// remove `noArgsClass` from `_.isEqual`
.replace(/if *\(noArgsClass[^}]+?}\n/, '');
@@ -628,17 +580,6 @@
.replace(/ *\|\| *\(noNodeClass *&&[\s\S]+?\)\)\)/, '');
}
- /**
- * Removes the "use strict" directive from `source`.
- *
- * @private
- * @param {String} source The source to process.
- * @returns {String} Returns the modified source.
- */
- function removeUseStrictDirective(source) {
- return source.replace(/(["'])use strict\1;( *\n)?/, '');
- }
-
/**
* Removes a given variable from `source`.
*
@@ -719,445 +660,685 @@
.replace(/\s*.+?\.useStrict *=.+/, '');
}
+ /*--------------------------------------------------------------------------*/
+
/**
- * Writes `source` to a file with the given `filename` to the current
- * working directory.
+ * Creates a debug and minified build, executing the `callback` for each.
+ * The `callback` is invoked with 2 arguments; (filepath, source)
*
- * @private
- * @param {String} source The source to write.
- * @param {String} filename The name of the file.
+ * @param {Array} options The options array.
+ * @param {Function} callback The function called per build.
*/
- function writeFile(source, filename) {
- // correct overly aggressive Closure Compiler minification
- source = source.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}');
+ function build(options, callback) {
+ options || (options = []);
+
+ // the debug version of `source`
+ var debugSource;
- // re-remove "use strict" added by the minifier
- if (!isStrict) {
- source = removeUseStrictDirective(source);
+ // used to report invalid command-line arguments
+ var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
+ if (/^(?:-o|--output)$/.test(options[index - 1]) ||
+ /^(?:category|exclude|exports|iife|include)=.*$/.test(value)) {
+ return true;
+ }
+ return [
+ 'backbone',
+ 'csp',
+ 'legacy',
+ 'mobile',
+ 'strict',
+ 'underscore',
+ '-c', '--stdout',
+ '-h', '--help',
+ '-o', '--output',
+ '-s', '--silent',
+ '-V', '--version'
+ ].indexOf(value) > -1;
+ });
+
+ // report invalid arguments
+ if (invalidArgs.length) {
+ console.log(
+ '\n' +
+ 'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
+ ' passed: ' + invalidArgs.join(', ')
+ );
+ displayHelp();
+ return;
}
- fs.writeFileSync(path.join(cwd, filename), source);
- }
- /*--------------------------------------------------------------------------*/
+ // display help message
+ if (_.find(options, function(arg) {
+ return /^(?:-h|--help)$/.test(arg);
+ })) {
+ displayHelp();
+ return;
+ }
- // display help message
- if (lodash.find(process.argv, function(arg) {
- return /^(?:-h|--help)$/.test(arg);
- })) {
- displayHelp();
- process.exit();
- }
+ // display `lodash.VERSION`
+ if (_.find(options, function(arg) {
+ return /^(?:-V|--version)$/.test(arg);
+ })) {
+ console.log(_.VERSION);
+ return;
+ }
- // display `lodash.VERSION`
- if (lodash.find(process.argv, function(arg) {
- return /^(?:-V|--version)$/.test(arg);
- })) {
- console.log(lodash.VERSION);
- process.exit();
- }
+ /*------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
+ // collections of method names to exclude or include
+ var excludeMethods = [],
+ includeMethods = [];
- // don't expose `_.forIn` or `_.forOwn` if `isUnderscore` is `true` unless
- // requested by `include`
- if (isUnderscore) {
- if (includeMethods.indexOf('forIn') == -1) {
- source = source.replace(/ *lodash\.forIn *=.+\n/, '');
- }
- if (includeMethods.indexOf('forOwn') == -1) {
- source = source.replace(/ *lodash\.forOwn *=.+\n/, '');
- }
- }
+ // flag used to specify a Backbone build
+ var isBackbone = options.indexOf('backbone') > -1;
- // add methods required by Backbone or Underscore
- [
- { 'flag': isBackbone, 'methodNames': backboneDependencies },
- { 'flag': isUnderscore, 'methodNames': underscoreMethods }
- ]
- .some(function(data) {
- var flag = data.flag,
- methodNames = data.methodNames;
-
- if (!flag) {
- return false;
- }
- // add any additional sub-dependencies
- methodNames = getDependencies(methodNames);
+ // flag used to specify a Content Security Policy build
+ var isCSP = options.indexOf('csp') > -1 || options.indexOf('CSP') > -1;
- if (filterType == 'exclude') {
- // remove excluded methods from `methodNames`
- includeMethods = lodash.without.apply(lodash, [methodNames].concat(excludeMethods));
- }
- else if (filterType) {
- // merge `methodNames` into `includeMethods`
- includeMethods = lodash.union(includeMethods, methodNames);
- }
- else {
- // include only the `methodNames`
- includeMethods = methodNames;
- }
- filterType = 'include';
- return true;
- });
+ // flag used to specify a legacy build
+ var isLegacy = options.indexOf('legacy') > -1;
- /*--------------------------------------------------------------------------*/
+ // flag used to specify an Underscore build
+ var isUnderscore = options.indexOf('underscore') > -1;
- // add category methods
- process.argv.some(function(value) {
- var categories = value.match(/^category=(.*)$/);
- if (!categories) {
- return false;
- }
- // resolve method names belonging to each category
- var categoryMethods = categories.reduce(function(result, category) {
- return result.concat(allMethods.filter(function(funcName) {
- return RegExp('@category ' + category + '\\b', 'i').test(matchFunction(source, funcName));
- }));
- }, []);
+ // flag used to specify a mobile build
+ var isMobile = !isLegacy && (isCSP || isUnderscore || options.indexOf('mobile') > -1);
- if (filterType == 'exclude') {
- // remove excluded methods from `categoryMethods`
- includeMethods = lodash.without.apply(lodash, [categoryMethods].concat(excludeMethods));
- }
- else if (filterType) {
- // merge `categoryMethods` into `includeMethods`
- includeMethods = lodash.union(includeMethods, categoryMethods);
- }
- else {
- // include only the `categoryMethods`
- includeMethods = categoryMethods;
- }
- filterType = 'include';
- return true;
- });
+ // flag used to specify writing output to standard output
+ var isStdOut = options.indexOf('-c') > -1 || options.indexOf('--stdout') > -1;
- /*--------------------------------------------------------------------------*/
+ // flag used to specify skipping status updates normally logged to the console
+ var isSilent = isStdOut || options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
- // custom build
- (function() {
- // exit early if "exclude" or "include" options aren't specified
- if (!filterType) {
- return;
- }
- if (filterType == 'exclude') {
- // remove methods that are named in `excludeMethods` and their dependants
- excludeMethods.forEach(function(funcName) {
- getDependants(funcName).concat(funcName).forEach(function(otherName) {
- source = removeFunction(source, otherName);
- });
+ // flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
+ // constructed using the "use strict" directive
+ var isStrict = options.indexOf('strict') > -1;
+
+ // flag used to specify if the build should include the "use strict" directive
+ var useStrict = isStrict || !(isLegacy || isMobile);
+
+ // the lodash.js source
+ var source = fs.readFileSync(path.join(__dirname, 'lodash.js'), 'utf8');
+
+ // used to specify the ways to export the `LoDash` function
+ var exportsOptions = options.reduce(function(result, value) {
+ var match = value.match(/^exports=(.*)$/);
+ if (!match) {
+ return result;
+ }
+ return match[1].split(/, */).sort();
+ }, exportsAll.slice());
+
+ // used to specify whether filtering is for exclusion or inclusion
+ var filterType = options.reduce(function(result, value) {
+ if (result) {
+ return result;
+ }
+ var pair = value.match(/^(exclude|include)=(.*)$/);
+ if (!pair) {
+ return result;
+ }
+ // remove nonexistent method names
+ var methodNames = _.intersection(allMethods, pair[2].split(/, */).map(getRealName));
+
+ if (pair[1] == 'exclude') {
+ excludeMethods = methodNames;
+ } else {
+ includeMethods = methodNames;
+ }
+ // return `filterType`
+ return pair[1];
+ }, '');
+
+ // used to specify a custom IIFE to wrap Lo-Dash
+ var iife = options.reduce(function(result, value) {
+ return result || (result = value.match(/^iife=(.*)$/)) && result[1];
+ }, '');
+
+ // load customized Lo-Dash module
+ var lodash = (function() {
+ var context = vm.createContext({
+ 'clearTimeout': clearTimeout,
+ 'setTimeout': setTimeout
});
- }
- else {
- // add dependencies to `includeMethods`
- includeMethods = getDependencies(includeMethods);
- // remove methods that aren't named in `includeMethods`
- lodash.each(allMethods, function(otherName) {
- if (!lodash.contains(includeMethods, otherName)) {
- source = removeFunction(source, otherName);
+ if (isStrict) {
+ source = setUseStrictOption(source, true);
+ } else {
+ // remove "use strict" directive
+ source = source.replace(/(["'])use strict\1;( *\n)?/, '');
+ if (!useStrict) {
+ source = setUseStrictOption(source, false);
}
- });
- }
+ }
+ if (isLegacy) {
+ ['isBindFast', 'isKeysFast', 'isStrictFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
+ source = replaceVar(source, varName, 'false');
+ });
- // remove `isArguments` fallback before `isArguments` is transformed by
- // other parts of the build process
- if (isRemoved(source, 'isArguments')) {
- source = removeIsArgumentsFallback(source);
- }
- }());
+ source = replaceVar(source, 'noArgsClass', 'true');
+ source = removeKeysOptimization(source);
+ }
+ else if (isUnderscore) {
+ // remove `deep` clone functionality
+ source = source.replace(/( +)function clone[\s\S]+?\n\1}/, [
+ ' function clone(value) {',
+ ' if (value == null) {',
+ ' return value;',
+ ' }',
+ ' var isObj = objectTypes[typeof value];',
+ ' if (isObj && value.clone && isFunction(value.clone)) {',
+ ' return value.clone(deep);',
+ ' }',
+ ' if (isObj) {',
+ ' var className = toString.call(value);',
+ ' if (!cloneableClasses[className] || (noArgsClass && isArguments(value))) {',
+ ' return value;',
+ ' }',
+ ' var isArr = className == arrayClass;',
+ ' }',
+ ' return isObj',
+ ' ? (isArr ? slice.call(value) : extend({}, value))',
+ ' : value;',
+ ' }'
+ ].join('\n'));
+ }
+ if (isMobile) {
+ source = replaceVar(source, 'isKeysFast', 'false');
+ source = removeKeysOptimization(source);
- /*--------------------------------------------------------------------------*/
+ // remove Opera 10.53-10.60 JIT fixes
+ source = source.replace(/length *> *-1 *&& *length/g, 'length');
- // simplify template snippets by removing unnecessary brackets
- source = source.replace(
- RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *([,\\n])", 'g'), "$1'$2"
- );
+ // remove `prototype` [[Enumerable]] fix from `_.keys`
+ source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(.+?propertyIsEnumerable[\s\S]+?\n\1}/, '');
- source = source.replace(
- RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *\\+", 'g'), "$1;\\n'+"
- );
+ // remove `prototype` [[Enumerable]] fix from `iteratorTemplate`
+ source = source
+ .replace(/(?: *\/\/.*\n)*\s*' *(?:<% *)?if *\(!hasDontEnumBug *(?:&&|\))[\s\S]+?<% *} *(?:%>|').+/g, '')
+ .replace(/!hasDontEnumBug *\|\|/g, '');
+ }
+ vm.runInContext(source, context);
+ return context._;
+ }());
+
+ /*------------------------------------------------------------------------*/
+
+ // customize for Backbone and Underscore builds
+ if (isUnderscore) {
+ // don't expose `_.forIn` or `_.forOwn` if `isUnderscore` is `true` unless
+ // requested by `include`
+ if (includeMethods.indexOf('forIn') == -1) {
+ source = source.replace(/ *lodash\.forIn *=.+\n/, '');
+ }
+ if (includeMethods.indexOf('forOwn') == -1) {
+ source = source.replace(/ *lodash\.forOwn *=.+\n/, '');
+ }
+ }
- /*--------------------------------------------------------------------------*/
+ // include methods required by Backbone and Underscore builds
+ [
+ { 'flag': isBackbone, 'methodNames': backboneDependencies },
+ { 'flag': isUnderscore, 'methodNames': underscoreMethods }
+ ]
+ .some(function(data) {
+ var flag = data.flag,
+ methodNames = data.methodNames;
+
+ if (!flag) {
+ return false;
+ }
+ // add any additional sub-dependencies
+ methodNames = getDependencies(methodNames);
- // DRY out isType functions
- (function() {
- var iteratorName = lodash.find(['forEach', 'forOwn'], function(funcName) {
- return !isRemoved(source, funcName);
+ if (filterType == 'exclude') {
+ // remove excluded methods from `methodNames`
+ includeMethods = _.without.apply(_, [methodNames].concat(excludeMethods));
+ }
+ else if (filterType) {
+ // merge `methodNames` into `includeMethods`
+ includeMethods = _.union(includeMethods, methodNames);
+ }
+ else {
+ // include only the `methodNames`
+ includeMethods = methodNames;
+ }
+ filterType = 'include';
+ return true;
});
- // skip this optimization if there are no iteration methods to use
- if (!iteratorName) {
- return;
- }
- var funcNames = [],
- objectSnippets = [];
-
- // build replacement code
- lodash.forOwn({
- 'Date': 'dateClass',
- 'Number': 'numberClass',
- 'RegExp': 'regexpClass',
- 'String': 'stringClass'
- }, function(value, key) {
- var funcName = 'is' + key,
- funcCode = matchFunction(source, funcName);
-
- if (funcCode) {
- funcNames.push(funcName);
- objectSnippets.push("'" + key + "': " + value);
+ /*------------------------------------------------------------------------*/
+
+ // include methods by category
+ options.some(function(value) {
+ var categories = value.match(/^category=(.*)$/);
+ if (!categories) {
+ return false;
}
+ // resolve method names belonging to each category
+ var categoryMethods = categories[1].split(/, */).reduce(function(result, category) {
+ return result.concat(allMethods.filter(function(methodName) {
+ return RegExp('@category ' + category + '\\b', 'i').test(matchFunction(source, methodName));
+ }));
+ }, []);
+
+ if (filterType == 'exclude') {
+ // remove excluded methods from `categoryMethods`
+ includeMethods = _.without.apply(_, [categoryMethods].concat(excludeMethods));
+ }
+ else if (filterType) {
+ // merge `categoryMethods` into `includeMethods`
+ includeMethods = _.union(includeMethods, categoryMethods);
+ }
+ else {
+ // include only the `categoryMethods`
+ includeMethods = categoryMethods;
+ }
+ filterType = 'include';
+ return true;
});
- // skip this optimization if there are less than 2 isType functions
- if (funcNames.length < 2) {
- return;
- }
+ /*------------------------------------------------------------------------*/
- // remove existing isType functions
- funcNames.forEach(function(funcName) {
- source = removeFunction(source, funcName);
- });
+ // remove methods from the build
+ (function() {
+ // exit early if "exclude" or "include" options aren't specified
+ if (!filterType) {
+ return;
+ }
+ if (filterType == 'exclude') {
+ // remove methods that are named in `excludeMethods` and their dependants
+ excludeMethods.forEach(function(methodName) {
+ getDependants(methodName).concat(methodName).forEach(function(otherName) {
+ source = removeFunction(source, otherName);
+ });
+ });
+ }
+ else {
+ // add dependencies to `includeMethods`
+ includeMethods = getDependencies(includeMethods);
+
+ // remove methods that aren't named in `includeMethods`
+ allMethods.forEach(function(otherName) {
+ if (!_.contains(includeMethods, otherName)) {
+ source = removeFunction(source, otherName);
+ }
+ });
+ }
+ }());
- // insert new DRY code after the method assignments
- var snippet = getMethodAssignments(source);
- source = source.replace(snippet, snippet + '\n' +
- ' // add `_.' + funcNames.join('`, `_.') + '`\n' +
- ' ' + iteratorName + '({\n ' + objectSnippets.join(',\n ') + '\n }, function(className, key) {\n' +
- " lodash['is' + key] = function(value) {\n" +
- ' return toString.call(value) == className;\n' +
- ' };\n' +
- ' });\n'
- );
- }());
+ /*------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
+ // simplify template snippets by removing unnecessary brackets
+ source = source.replace(
+ RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *([,\\n])", 'g'), "$1'$2"
+ );
- if (isLegacy) {
- ['isBindFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
- source = removeVar(source, varName);
- });
+ source = source.replace(
+ RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *\\+", 'g'), "$1;\\n'+"
+ );
- ['bind', 'isArray'].forEach(function(funcName) {
- var snippet = matchFunction(source, funcName),
- modified = snippet;
+ // remove `isArguments` fallback before `isArguments` is transformed by
+ // other parts of the build process
+ if (isRemoved(source, 'isArguments')) {
+ source = removeIsArgumentsFallback(source);
+ }
+ // DRY out isType functions
+ (function() {
+ var iteratorName = _.find(['forEach', 'forOwn'], function(methodName) {
+ return !isRemoved(source, methodName);
+ });
- // remove native `Function#bind` branch in `_.bind`
- if (funcName == 'bind') {
- modified = modified.replace(/(?:\s*\/\/.*)*\s*else if *\(isBindFast[^}]+}/, '');
+ // skip this optimization if there are no iteration methods to use
+ if (!iteratorName) {
+ return;
}
- // remove native `Array.isArray` branch in `_.isArray`
- else {
- modified = modified.replace(/nativeIsArray * \|\|/, '');
+ var funcNames = [],
+ objectSnippets = [];
+
+ // build replacement code
+ _.forOwn({
+ 'Arguments': 'argsClass',
+ 'Date': 'dateClass',
+ 'Number': 'numberClass',
+ 'RegExp': 'regexpClass',
+ 'String': 'stringClass'
+ },
+ function(value, key) {
+ if (!isUnderscore && key == 'Arguments') {
+ return;
+ }
+ var funcName = 'is' + key,
+ funcCode = matchFunction(source, funcName);
+
+ if (funcCode) {
+ funcNames.push(funcName);
+ objectSnippets.push("'" + key + "': " + value);
+ }
+ });
+
+ // skip this optimization if there are less than 2 isType functions
+ if (funcNames.length < 2) {
+ return;
}
- source = source.replace(snippet, modified);
- });
- // replace `_.keys` with `shimKeys`
- if (!isRemoved(source, 'keys')) {
- source = source.replace(
- matchFunction(source, 'keys').replace(/[\s\S]+?var keys *=/, ''),
- matchFunction(source, 'shimKeys').replace(/[\s\S]+?var shimKeys *=/, '')
- );
+ // remove existing isType functions
+ funcNames.forEach(function(funcName) {
+ source = removeFunction(source, funcName);
+ });
- source = removeFunction(source, 'shimKeys');
- }
- // replace `_.isArguments` with fallback
- if (!isRemoved(source, 'isArguments')) {
- source = source.replace(
- matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
- getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n'
+ // insert new DRY code after the method assignments
+ var snippet = getMethodAssignments(source);
+ source = source.replace(snippet, snippet + '\n' +
+ ' // add `_.' + funcNames.join('`, `_.') + '`\n' +
+ ' ' + iteratorName + '({\n ' + objectSnippets.join(',\n ') + '\n }, function(className, key) {\n' +
+ " lodash['is' + key] = function(value) {\n" +
+ ' return toString.call(value) == className;\n' +
+ ' };\n' +
+ ' });\n'
);
+ }());
- source = removeIsArgumentsFallback(source);
+ /*------------------------------------------------------------------------*/
+
+ if (isLegacy) {
+ ['isBindFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
+ source = removeVar(source, varName);
+ });
+
+ ['bind', 'isArray'].forEach(function(methodName) {
+ var snippet = matchFunction(source, methodName),
+ modified = snippet;
+
+ // remove native `Function#bind` branch in `_.bind`
+ if (methodName == 'bind') {
+ modified = modified.replace(/(?:\s*\/\/.*)*\s*else if *\(isBindFast[^}]+}/, '');
+ }
+ // remove native `Array.isArray` branch in `_.isArray`
+ else {
+ modified = modified.replace(/nativeIsArray * \|\|/, '');
+ }
+ source = source.replace(snippet, modified);
+ });
+
+ // replace `_.keys` with `shimKeys`
+ if (!isRemoved(source, 'keys')) {
+ source = source.replace(
+ matchFunction(source, 'keys').replace(/[\s\S]+?var keys *=/, ''),
+ matchFunction(source, 'shimKeys').replace(/[\s\S]+?var shimKeys *=/, '')
+ );
+
+ source = removeFunction(source, 'shimKeys');
+ }
+ // replace `_.isArguments` with fallback
+ if (!isRemoved(source, 'isArguments')) {
+ source = source.replace(
+ matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
+ getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n'
+ );
+
+ source = removeIsArgumentsFallback(source);
+ }
+
+ source = removeVar(source, 'reNative');
+ source = removeFromCreateIterator(source, 'nativeKeys');
}
- source = removeVar(source, 'reNative');
- source = removeFromCreateIterator(source, 'nativeKeys');
- source = removeKeysOptimization(source);
- }
+ if (isMobile) {
+ // inline all functions defined with `createIterator`
+ _.functions(lodash).forEach(function(methodName) {
+ // match `methodName` with pseudo private `_` prefixes removed to allow matching `shimKeys`
+ var reFunc = RegExp('(\\bvar ' + methodName.replace(/^_/, '') + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
+
+ // skip if not defined with `createIterator`
+ if (!reFunc.test(source)) {
+ return;
+ }
+ // extract, format, and inject the compiled function's source code
+ source = source.replace(reFunc, '$1' + getFunctionSource(lodash[methodName]) + ';\n');
+ });
- if (isMobile) {
- // inline all functions defined with `createIterator`
- lodash.functions(lodash).forEach(function(funcName) {
- // match `funcName` with pseudo private `_` prefixes removed to allow matching `shimKeys`
- var reFunc = RegExp('(\\bvar ' + funcName.replace(/^_/, '') + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n');
+ // replace `callee` in `_.merge` with `merge`
+ source = source.replace(matchFunction(source, 'merge'), function(match) {
+ return match.replace(/\bcallee\b/g, 'merge');
+ });
- // skip if not defined with `createIterator`
- if (!reFunc.test(source)) {
- return;
+ if (!isUnderscore) {
+ source = removeIsArgumentsFallback(source);
+ source = removeNoArgsClass(source);
}
- // extract, format, and inject the compiled function's source code
- source = source.replace(reFunc, '$1' + getFunctionSource(lodash[funcName]) + ';\n');
- });
- // replace `callee` in `_.merge` with `merge`
- source = source.replace(matchFunction(source, 'merge'), function(match) {
- return match.replace(/\bcallee\b/g, 'merge');
- });
+ // remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, `noArgsEnum` assignment
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b[\s\S]+?}\(1\)\);\n/, '');
- if (!isUnderscore) {
- source = removeIsArgumentsFallback(source);
- source = removeIsPlainObjectFallback(source);
- source = removeNoArgsClass(source);
+ // remove `iteratesOwnLast` from `isPlainObject`
+ source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(iteratesOwnLast[\s\S]+?\n\1}/, '');
+
+ // remove JScript [[DontEnum]] fix from `_.isEqual`
+ source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(hasDontEnumBug[\s\S]+?\n\1}/, '');
+
+ // remove `hasObjectSpliceBug` fix from the mutator Array functions mixin
+ source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(hasObjectSpliceBug[\s\S]+?\n\1}/, '');
+
+ // remove `noArraySliceOnStrings` from `_.toArray`
+ source = source.replace(/noArraySliceOnStrings *\?[^:]+: *([^)]+)/g, '$1');
+
+ // remove `noCharByIndex` from `_.reduceRight`
+ source = source.replace(/noCharByIndex *&&[^:]+: *([^;]+)/g, '$1');
+
+ source = removeVar(source, 'extendIteratorOptions');
+ source = removeVar(source, 'iteratorTemplate');
+ source = removeVar(source, 'noArraySliceOnStrings');
+ source = removeVar(source, 'noCharByIndex');
+ source = removeNoNodeClass(source);
}
+ else {
+ // inline `iteratorTemplate` template
+ source = source.replace(/(( +)var iteratorTemplate *= *)[\s\S]+?\n\2.+?;\n/, (function() {
+ var snippet = getFunctionSource(lodash._iteratorTemplate);
+
+ // prepend data object references to property names to avoid having to
+ // use a with-statement
+ iteratorOptions.forEach(function(property) {
+ snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
+ });
- // remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, `noArgsEnum` assignment
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b[\s\S]+?}\(1\)\);\n/, '');
+ // remove unnecessary code
+ snippet = snippet
+ .replace(/var __t.+/, "var __p = '';")
+ .replace(/function print[^}]+}/, '')
+ .replace(/'(?:\\n|\s)+'/g, "''")
+ .replace(/__p *\+= *' *';/g, '')
+ .replace(/(__p *\+= *)' *' *\+/g, '$1')
+ .replace(/(\{) *;|; *(\})/g, '$1$2')
+ .replace(/\(\(__t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__t\)/g, '$1');
+
+ // remove the with-statement
+ snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1');
+
+ // minor cleanup
+ snippet = snippet
+ .replace(/obj *\|\| *\(obj *= *\{}\);/, '')
+ .replace(/var __p = '';\s*__p \+=/, 'var __p =');
+
+ // remove comments, including sourceURLs
+ snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, '');
+
+ return '$1' + snippet + ';\n';
+ }()));
+ }
- // remove `iteratesOwnLast` from `isPlainObject`
- source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(iteratesOwnLast[\s\S]+?\n\1}/, '');
+ /*------------------------------------------------------------------------*/
- // remove JScript [[DontEnum]] fix from `_.isEqual`
- source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(hasDontEnumBug[\s\S]+?\n\1}/, '');
+ // customize Lo-Dash's export bootstrap
+ if (exportsOptions.indexOf('amd') == -1) {
+ source = source.replace(/(?: *\/\/.*\n)*( +)if *\(typeof +define[\s\S]+?else /, '$1');
+ }
+ if (exportsOptions.indexOf('node') == -1) {
+ source = source.replace(/(?: *\/\/.*\n)* *if *\(typeof +module[\s\S]+?else *{\n([\s\S]+?) *}\n/, '$1');
+ }
+ if (exportsOptions.indexOf('commonjs') == -1) {
+ source = source.replace(/(?: *\/\/.*\n)*(?:( +)else *{)?\s*freeExports\._ *=.+(\n\1})?\n/, '');
+ }
+ if (exportsOptions.indexOf('global') == -1) {
+ source = source.replace(/(?:( +)else *{)?(?:\s*\/\/.*)*\s*window\._ *= *lodash.+(\n\1})?\n/g, '');
+ }
- // remove `hasObjectSpliceBug` fix from the mutator Array functions mixin
- source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(hasObjectSpliceBug[\s\S]+?\n\1}/, '');
+ // remove `if (freeExports) {...}` if it's empty
+ source = source.replace(/(?: *\/\/.*\n)* *(?:else )?if *\(freeExports\) *{\s*}(?:\s*else *{\n([\s\S]+?) *})?/, '$1');
- // remove `noArraySliceOnStrings` from `_.toArray`
- source = source.replace(/noArraySliceOnStrings *\?[^:]+: *([^)]+)/g, '$1');
+ /*------------------------------------------------------------------------*/
- // remove `noCharByIndex` from `_.reduceRight`
- source = source.replace(/noCharByIndex *&&[^:]+: *([^;]+)/g, '$1');
+ // customize Lo-Dash's IIFE
+ (function() {
+ if (iife) {
+ var token = '%output%',
+ index = iife.indexOf(token);
- source = removeVar(source, 'extendIteratorOptions');
- source = removeVar(source, 'iteratorTemplate');
- source = removeVar(source, 'noArraySliceOnStrings');
- source = removeVar(source, 'noCharByIndex');
- source = removeKeysOptimization(source);
- source = removeNoNodeClass(source);
- }
- else {
- // inline `iteratorTemplate` template
- source = source.replace(/(( +)var iteratorTemplate *= *)[\s\S]+?\n\2.+?;\n/, (function() {
- var snippet = getFunctionSource(lodash._iteratorTemplate);
-
- // prepend data object references to property names to avoid having to
- // use a with-statement
- iteratorOptions.forEach(function(property) {
- snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
- });
+ source = source.match(/\/\*![\s\S]+?\*\/\n/) +
+ iife.slice(0, index) +
+ source.replace(/^[^(]+?\(function[^{]+?{|}\(this\)\)[;\s]*$/g, '') +
+ iife.slice(index + token.length);
+ }
+ }());
- // remove unnecessary code
- snippet = snippet
- .replace(/var __t.+/, "var __p = '';")
- .replace(/function print[^}]+}/, '')
- .replace(/'(?:\\n|\s)+'/g, "''")
- .replace(/__p *\+= *' *';/g, '')
- .replace(/(__p *\+= *)' *' *\+/g, '$1')
- .replace(/(\{) *;|; *(\})/g, '$1$2')
- .replace(/\(\(__t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__t\)/g, '$1');
-
- // remove the with-statement
- snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1');
-
- // minor cleanup
- snippet = snippet
- .replace(/obj *\|\| *\(obj *= *\{}\);/, '')
- .replace(/var __p = '';\s*__p \+=/, 'var __p =');
-
- // remove comments, including sourceURLs
- snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, '');
-
- return '$1' + snippet + ';\n';
- }()));
- }
+ /*------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
+ // modify/remove references to removed methods/variables
+ if (isRemoved(source, 'isArguments')) {
+ source = replaceVar(source, 'noArgsClass', 'false');
+ }
+ if (isRemoved(source, 'isFunction')) {
+ source = removeIsFunctionFallback(source);
+ }
+ if (isRemoved(source, 'mixin')) {
+ // remove `LoDash` constructor
+ source = removeFunction(source, 'LoDash');
+ // remove `LoDash` calls
+ source = source.replace(/(?:new +LoDash(?!\()|(?:new +)?LoDash\([^)]*\));?/g, '');
+ // remove `LoDash.prototype` additions
+ source = source.replace(/(?:\s*\/\/.*)*\s*LoDash.prototype *=[\s\S]+?\/\*-+\*\//, '');
+ // remove `hasObjectSpliceBug` assignment
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasObjectSpliceBug;|.+?hasObjectSpliceBug *=.+/g, '');
+ }
- // modify/remove references to removed methods/variables
- if (isRemoved(source, 'isArguments')) {
- source = replaceVar(source, 'noArgsClass', 'false');
- }
- if (isRemoved(source, 'isFunction')) {
- source = removeIsFunctionFallback(source);
- }
- if (isRemoved(source, 'mixin')) {
- // remove `LoDash` constructor
- source = removeFunction(source, 'LoDash');
- // remove `LoDash` calls
- source = source.replace(/(?:new +LoDash(?!\()|(?:new +)?LoDash\([^)]*\));?/g, '');
- // remove `LoDash.prototype` additions
- source = source.replace(/(?:\s*\/\/.*)*\s*LoDash.prototype *=[\s\S]+?\/\*-+\*\//, '');
- // remove `hasObjectSpliceBug` assignment
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasObjectSpliceBug;|.+?hasObjectSpliceBug *=.+/g, '');
- }
+ // remove pseudo private properties
+ source = source.replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n');
- // remove pseudo private properties
- source = source.replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n');
+ // assign debug source before further modifications that rely on the minifier
+ // to remove unused variables and other dead code
+ debugSource = source;
- // assign debug source before further modifications that rely on the minifier
- // to remove unused variables and other dead code
- debugSource = source;
+ // remove associated functions, variables, and code snippets that the minifier may miss
+ if (isRemoved(source, 'clone')) {
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var cloneableClasses *=[\s\S]+?true;\n/g, '');
+ }
+ if (isRemoved(source, 'isArray')) {
+ source = removeVar(source, 'nativeIsArray');
+ }
+ if (isRemoved(source, 'keys')) {
+ source = removeFunction(source, 'shimKeys');
+ }
+ if (isRemoved(source, 'template')) {
+ // remove `templateSettings` assignment
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
+ }
+ if (isRemoved(source, 'toArray')) {
+ source = removeVar(source, 'noArraySliceOnStrings');
+ }
+ if (isUnderscore
+ ? isRemoved(source, 'merge')
+ : isRemoved(source, 'clone', 'merge')
+ ) {
+ source = removeFunction(source, 'isPlainObject');
+ }
+ if (isRemoved(source, 'clone', 'isArguments', 'isEmpty', 'isEqual')) {
+ source = removeNoArgsClass(source);
+ }
+ if (isRemoved(source, 'isEqual', 'isPlainObject')) {
+ source = removeNoNodeClass(source);
+ }
+ if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
+ source = removeFunction(source, 'createIterator');
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var noArgsEnum;|.+?noArgsEnum *=.+/g, '');
+ }
+ if (isRemoved(source, 'createIterator', 'bind')) {
+ source = removeVar(source, 'isBindFast');
+ source = removeVar(source, 'isStrictFast');
+ source = removeVar(source, 'nativeBind');
+ }
+ if (isRemoved(source, 'createIterator', 'bind', 'isArray', 'keys')) {
+ source = removeVar(source, 'reNative');
+ }
+ if (isRemoved(source, 'createIterator', 'isEmpty', 'isEqual')) {
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var arrayLikeClasses *=[\s\S]+?true;\n/g, '');
+ }
+ if (isRemoved(source, 'createIterator', 'isEqual')) {
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug;|.+?hasDontEnumBug *=.+/g, '');
+ }
+ if (isRemoved(source, 'createIterator', 'isPlainObject')) {
+ source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var iteratesOwnLast;|.+?iteratesOwnLast *=.+/g, '');
+ }
+ if (isRemoved(source, 'createIterator', 'keys')) {
+ source = removeVar(source, 'nativeKeys');
+ }
+ if (!source.match(/var (?:hasDontEnumBug|hasObjectSpliceBug|iteratesOwnLast|noArgsEnum)\b/g)) {
+ // remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, and `noArgsEnum` assignment
+ source = source.replace(/ *\(function\(\) *{[\s\S]+?}\(1\)\);/, '');
+ }
- // remove associated functions, variables, and code snippets that the minifier may miss
- if (isRemoved(source, 'isArray')) {
- source = removeVar(source, 'nativeIsArray');
- }
- if (isRemoved(source, 'keys')) {
- source = removeFunction(source, 'shimKeys');
- }
- if (isRemoved(source, 'template')) {
- // remove `templateSettings` assignment
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
- }
- if (isRemoved(source, 'toArray')) {
- source = removeVar(source, 'noArraySliceOnStrings');
- }
- if (isRemoved(source, 'clone', 'merge')) {
- source = removeFunction(source, 'isPlainObject');
- }
- if (isRemoved(source, 'clone', 'isArguments', 'isEmpty', 'isEqual', 'size')) {
- source = removeNoArgsClass(source);
- }
- if (isRemoved(source, 'isEqual', 'isPlainObject')) {
- source = removeNoNodeClass(source);
- }
- if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
- source = removeFunction(source, 'createIterator');
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var noArgsEnum;|.+?noArgsEnum *=.+/g, '');
- }
- if (isRemoved(source, 'createIterator', 'bind')) {
- source = removeVar(source, 'isBindFast');
- source = removeVar(source, 'isStrictFast');
- source = removeVar(source, 'nativeBind');
- }
- if (isRemoved(source, 'createIterator', 'bind', 'isArray', 'keys')) {
- source = removeVar(source, 'reNative');
- }
- if (isRemoved(source, 'createIterator', 'clone', 'merge')) {
- source = removeIsPlainObjectFallback(source);
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var iteratesOwnLast;|.+?iteratesOwnLast *=.+/g, '');
- }
- if (isRemoved(source, 'createIterator', 'isEqual')) {
- source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug;|.+?hasDontEnumBug *=.+/g, '');
- }
- if (isRemoved(source, 'createIterator', 'keys')) {
- source = removeVar(source, 'nativeKeys');
- }
- if (!source.match(/var (?:hasDontEnumBug|hasObjectSpliceBug|iteratesOwnLast|noArgsEnum)\b/g)) {
- // remove `hasDontEnumBug`, `hasObjectSpliceBug`, `iteratesOwnLast`, and `noArgsEnum` assignment
- source = source.replace(/ *\(function\(\) *{[\s\S]+?}\(1\)\);/, '');
- }
+ debugSource = cleanupSource(debugSource);
+ source = cleanupSource(source);
+
+ /*------------------------------------------------------------------------*/
- // consolidate consecutive horizontal rule comment separators
- source = source.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
- return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
- });
+ // used to specify creating a custom build
+ var isCustom = !_.isEqual(exportsOptions, exportsAll) || filterType || iife || isBackbone || isLegacy || isMobile || isStrict || isUnderscore;
- // cleanup code
- source = source.replace(/^ *;\n/gm, '');
+ // used to specify the output path for builds
+ var outputPath = options.reduce(function(result, value, index) {
+ return result || (/^(?:-o|--output)$/.test(value) ? options[index + 1] : result);
+ }, '');
- // begin the minification process
- if (filterType || isBackbone || isLegacy || isMobile || isStrict || isUnderscore) {
- writeFile(debugSource, 'lodash.custom.js');
+ // used to name temporary files created in `dist/`
+ var workingName = 'lodash' + (isCustom ? '.custom' : '') + '.min';
- minify(source, 'lodash.custom.min', function(result) {
- writeFile(result, 'lodash.custom.min.js');
+ // output debug build
+ if (isCustom && !outputPath && !isStdOut) {
+ callback(debugSource, path.join(cwd, 'lodash.custom.js'));
+ }
+ // begin the minification process
+ minify(source, {
+ 'silent': isSilent,
+ 'workingName': workingName,
+ 'onComplete': function(source) {
+ // correct overly aggressive Closure Compiler minification
+ source = source.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}');
+
+ // inject "use strict" directive
+ if (isStrict) {
+ source = source.replace(/^(\/\*![\s\S]+?\*\/\n;\(function[^)]+\){)([^'"])/, '$1"use strict";$2');
+ }
+ if (isStdOut) {
+ stdout.write(source);
+ callback(source);
+ } else {
+ callback(source, outputPath || path.join(cwd, workingName + '.js'));
+ }
+ }
});
}
+
+ /*--------------------------------------------------------------------------*/
+
+ // expose `build`
+ if (module != require.main) {
+ module.exports = build;
+ }
else {
- minify(source, 'lodash.min', function(result) {
- writeFile(result, 'lodash.min.js');
+ // or invoked directly
+ build(process.argv, function(source, filepath) {
+ filepath && fs.writeFileSync(filepath, source, 'utf8');
});
}
}());
diff --git a/build/minify.js b/build/minify.js
index 29e355d33a..b04571a965 100755
--- a/build/minify.js
+++ b/build/minify.js
@@ -25,7 +25,6 @@
/** Closure Compiler command-line options */
var closureOptions = [
'--compilation_level=ADVANCED_OPTIMIZATIONS',
- '--language_in=ECMASCRIPT5_STRICT',
'--warning_level=QUIET'
];
@@ -38,12 +37,33 @@
* The exposed `minify` function minifies a given Lo-Dash `source` and invokes
* the `onComplete` callback when finished.
*
- * @param {String} source The source to minify.
- * @param {String} workingName The name to give temporary files creates during the minification process.
- * @param {Function} onComplete A function called when minification has completed.
+ * @param {Array|String} source The array of command-line arguments or the
+ * source to minify.
+ * @param {Object} options The options object containing `onComplete`,
+ * `silent`, and `workingName`.
*/
- function minify(source, workingName, onComplete) {
- new Minify(source, workingName, onComplete);
+ function minify(source, options) {
+ options || (options = {});
+
+ if (Array.isArray(source)) {
+ // convert the command-line arguments to an options object
+ options = source;
+ var filePath = options[options.length - 1],
+ dirPath = path.dirname(filePath),
+ workingName = path.basename(filePath, '.js') + '.min',
+ outputPath = path.join(dirPath, workingName + '.js'),
+ isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
+
+ source = fs.readFileSync(filePath, 'utf8');
+ options = {
+ 'silent': isSilent,
+ 'workingName': workingName,
+ 'onComplete': function(source) {
+ fs.writeFileSync(outputPath, source, 'utf8');
+ }
+ };
+ }
+ new Minify(source, options);
}
/**
@@ -52,10 +72,17 @@
* @private
* @constructor
* @param {String} source The source to minify.
- * @param {String} workingName The name to give temporary files creates during the minification process.
- * @param {Function} onComplete A function called when minification has completed.
+ * @param {Object} options The options object containing `onComplete`,
+ * `silent`, and `workingName`.
*/
- function Minify(source, workingName, onComplete) {
+ function Minify(source, options) {
+ source || (source = '');
+ options || (options = {});
+
+ if (typeof source != 'string') {
+ options = source || options;
+ source = options.source || '';
+ }
// create the destination directory if it doesn't exist
if (!fs.existsSync(distPath)) {
// avoid errors when called as a npm executable
@@ -67,9 +94,12 @@
this.compiled = {};
this.hybrid = {};
this.uglified = {};
- this.onComplete = onComplete;
- this.source = source = preprocess(source);
- this.workingName = workingName;
+ this.isSilent = !!options.silent;
+ this.onComplete = options.onComplete || function() {};
+ this.workingName = options.workingName || 'temp';
+
+ source = preprocess(source);
+ this.source = source;
// begin the minification process
closureCompile.call(this, source, onClosureCompile.bind(this));
@@ -98,10 +128,12 @@
message = null;
}
- console.log(message == null
- ? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
- : message
- );
+ if (!this.isSilent) {
+ console.log(message == null
+ ? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
+ : message
+ );
+ }
compiler.stdout.on('data', function(data) {
// append the data to the output stream
@@ -149,10 +181,12 @@
message = null;
}
- console.log(message == null
- ? 'Compressing ' + this.workingName + ' using UglifyJS...'
- : message
- );
+ if (!this.isSilent) {
+ console.log(message == null
+ ? 'Compressing ' + this.workingName + ' using UglifyJS...'
+ : message
+ );
+ }
try {
result = ugly.gen_code(
@@ -203,9 +237,12 @@
if (exception) {
throw exception;
}
+ if (!this.isSilent) {
+ console.log('Done. Size: %d bytes.', result.length);
+ }
+
// store the gzipped result and report the size
this.compiled.gzip = result;
- console.log('Done. Size: %d bytes.', result.length);
// next, minify the source using only UglifyJS
uglify.call(this, this.source, onUglify.bind(this));
@@ -238,11 +275,13 @@
if (exception) {
throw exception;
}
+ if (!this.isSilent) {
+ console.log('Done. Size: %d bytes.', result.length);
+ }
var message = 'Compressing ' + this.workingName + ' using hybrid minification...';
// store the gzipped result and report the size
this.uglified.gzip = result;
- console.log('Done. Size: %d bytes.', result.length);
// next, minify the Closure Compiler minified source using UglifyJS
uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
@@ -275,9 +314,11 @@
if (exception) {
throw exception;
}
+ if (!this.isSilent) {
+ console.log('Done. Size: %d bytes.', result.length);
+ }
// store the gzipped result and report the size
this.hybrid.gzip = result;
- console.log('Done. Size: %d bytes.', result.length);
// finish by choosing the smallest compressed file
onComplete.call(this);
@@ -334,14 +375,11 @@
// was invoked directly (e.g. `node minify.js source.js`) and write to
// `.min.js`
(function() {
- var filePath = process.argv[2],
- dirPath = path.dirname(filePath),
- source = fs.readFileSync(filePath, 'utf8'),
- workingName = path.basename(filePath, '.js') + '.min';
-
- minify(source, workingName, function(result) {
- fs.writeFileSync(path.join(dirPath, workingName + '.js'), result, 'utf8');
- });
+ var options = process.argv;
+ if (options.length < 3) {
+ return;
+ }
+ minify(options);
}());
}
}());
diff --git a/build/post-compile.js b/build/post-compile.js
index 4bd6d1999e..2b83991360 100644
--- a/build/post-compile.js
+++ b/build/post-compile.js
@@ -6,11 +6,15 @@
var fs = require('fs');
/** The minimal license/copyright template */
- var licenseTemplate =
- '/*!\n' +
- ' Lo-Dash @VERSION lodash.com/license\n' +
- ' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
- '*/';
+ var licenseTemplate = {
+ 'lodash':
+ '/*!\n' +
+ ' Lo-Dash @VERSION lodash.com/license\n' +
+ ' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
+ '*/',
+ 'underscore':
+ '/*! Underscore.js @VERSION github.com/documentcloud/underscore/blob/master/LICENSE */'
+ };
/*--------------------------------------------------------------------------*/
@@ -22,29 +26,29 @@
* @returns {String} Returns the processed source.
*/
function postprocess(source) {
- // exit early if snippet isn't found
- var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
- if (!snippet) {
- return source;
- }
-
- // set the version
- var license = licenseTemplate.replace('@VERSION', snippet[2]);
-
// move vars exposed by Closure Compiler into the IIFE
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
// unescape properties (i.e. foo["bar"] => foo.bar)
- source = source.replace(/(\w)\["([^."]+)"\]/g, '$1.$2');
+ source = source.replace(/(\w)\["([^."]+)"\]/g, function(match, left, right) {
+ return /\W/.test(right) ? match : (left + '.' + right);
+ });
// correct AMD module definition for AMD build optimizers
source = source.replace(/("function")\s*==\s*(typeof define)\s*&&\s*\(?\s*("object")\s*==\s*(typeof define\.amd)\s*&&\s*(define\.amd)\s*\)?/, '$2==$1&&$4==$3&&$5');
- // add license
- source = license + '\n;' + source;
-
// add trailing semicolon
- return source.replace(/[\s;]*$/, ';');
+ if (source) {
+ source = source.replace(/[\s;]*$/, ';');
+ }
+ // exit early if version snippet isn't found
+ var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
+ if (!snippet) {
+ return source;
+ }
+ // add license
+ return licenseTemplate[/call\(this\);?$/.test(source) ? 'underscore' : 'lodash']
+ .replace('@VERSION', snippet[2]) + '\n;' + source;
}
/*--------------------------------------------------------------------------*/
diff --git a/build/pre-compile.js b/build/pre-compile.js
index 6e5f4bcb83..08e0bef5d4 100644
--- a/build/pre-compile.js
+++ b/build/pre-compile.js
@@ -44,7 +44,7 @@
'callee',
'className',
'compareAscending',
- 'destValue',
+ 'data',
'forIn',
'found',
'funcs',
@@ -66,10 +66,11 @@
'propsLength',
'recursive',
'source',
- 'stack',
+ 'sources',
'stackLength',
'target',
- 'valueProp'
+ 'valueProp',
+ 'values'
];
/** Used to minify `compileIterator` option properties */
@@ -104,9 +105,9 @@
/** Used to protect the specified properties from getting minified */
var propWhitelist = [
'_',
- '_chain',
- '_wrapped',
+ '__chain__',
'__proto__',
+ '__wrapped__',
'after',
'all',
'amd',
@@ -117,6 +118,7 @@
'chain',
'clearTimeout',
'clone',
+ 'clones',
'collect',
'compact',
'compose',
@@ -135,6 +137,7 @@
'escape',
'evaluate',
'every',
+ 'exports',
'extend',
'filter',
'find',
@@ -157,6 +160,7 @@
'inject',
'interpolate',
'intersection',
+ 'invert',
'invoke',
'isArguments',
'isArray',
@@ -187,12 +191,15 @@
'min',
'mixin',
'noConflict',
+ 'object',
'omit',
'once',
'opera',
+ 'pairs',
'partial',
'pick',
'pluck',
+ 'random',
'range',
'reduce',
'reduceRight',
@@ -207,6 +214,9 @@
'sortBy',
'sortedIndex',
'source',
+ 'sources',
+ 'stackA',
+ 'stackB',
'tail',
'take',
'tap',
@@ -228,7 +238,10 @@
'without',
'wrap',
'zip',
- 'zipObject'
+
+ // properties used by underscore.js
+ '_chain',
+ '_wrapped'
];
/*--------------------------------------------------------------------------*/
@@ -246,22 +259,6 @@
// remove unrecognized JSDoc tags so Closure Compiler won't complain
source = source.replace(/@(?:alias|category)\b.*/g, '');
- // manually convert `arrayLikeClasses` property assignments because
- // Closure Compiler errors trying to minify them
- source = source.replace(/(arrayLikeClasses =)[\s\S]+?= *true/,
- "$1{'[object Arguments]': true, '[object Array]': true, '[object Boolean]': false, " +
- "'[object Date]': false, '[object Function]': false, '[object Number]': false, " +
- "'[object Object]': false, '[object RegExp]': false, '[object String]': true }"
- );
-
- // manually convert `cloneableClasses` property assignments because
- // Closure Compiler errors trying to minify them
- source = source.replace(/(cloneableClasses =)[\s\S]+?= *true/,
- "$1{'[object Arguments]': false, '[object Array]': true, '[object Boolean]': true, " +
- "'[object Date]': true, '[object Function]': false, '[object Number]': true, " +
- "'[object Object]': true, '[object RegExp]': true, '[object String]': true }"
- );
-
// add brackets to whitelisted properties so Closure Compiler won't mung them
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
@@ -269,6 +266,9 @@
// remove brackets from `_.escape()` in `_.template`
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
+ // remove brackets from `_.escape()` in underscore.js `_.template`
+ source = source.replace(/_\['escape'\]\(__t'/g, '_.escape(__t');
+
// remove brackets from `collection.indexOf` in `_.contains`
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
@@ -283,6 +283,9 @@
});
});
+ // add newline to `+"__p+='"` in underscore.js `_.template`
+ source = source.replace(/\+"__p\+='"/g, '+"\\n__p+=\'"');
+
// remove whitespace from `_.template` related regexes
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
return match.replace(/ |\\n/g, '');
@@ -302,10 +305,10 @@
// remove debug sourceURL use in `_.template`
source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');
- // minify internal properties used by 'compareAscending', `_.clone`, `_.merge`, and `_.sortBy`
+ // minify internal properties used by 'compareAscending', `_.clone`, `_.isEqual`, `_.merge`, and `_.sortBy`
(function() {
- var properties = ['criteria', 'index', 'source', 'value'],
- snippets = source.match(/( +)(?:function clone|function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
+ var properties = ['clones', 'criteria', 'index', 'sources', 'thorough', 'value', 'values'],
+ snippets = source.match(/( +)(?:function (?:clone|compareAscending|isEqual)|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
if (!snippets) {
return;
@@ -319,7 +322,7 @@
properties.forEach(function(property, index) {
var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
reDotProp = RegExp('\\.' + property + '\\b', 'g'),
- rePropColon = RegExp("(')?\\b" + property + "\\1 *:", 'g');
+ rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
if (isCompilable) {
// add quotes around properties in the inlined `_.merge` and `_.sortBy`
@@ -328,20 +331,20 @@
modified = modified
.replace(reBracketProp, "['" + minNames[index] + "']")
.replace(reDotProp, "['" + minNames[index] + "']")
- .replace(rePropColon, "'" + minNames[index] + "':");
+ .replace(rePropColon, "$1'" + minNames[index] + "':");
}
else {
modified = modified
.replace(reBracketProp, '.' + minNames[index])
.replace(reDotProp, '.' + minNames[index])
- .replace(rePropColon, minNames[index] + ':');
+ .replace(rePropColon, '$1' + minNames[index] + ':');
}
}
else {
modified = modified
.replace(reBracketProp, "['" + minNames[index] + "']")
.replace(reDotProp, '.' + minNames[index])
- .replace(rePropColon, "'" + minNames[index] + "':")
+ .replace(rePropColon, "$1'" + minNames[index] + "':")
// correct `value.source` in regexp branch of `_.clone`
if (property == 'source') {
diff --git a/component.json b/component.json
new file mode 100644
index 0000000000..5fd89537ea
--- /dev/null
+++ b/component.json
@@ -0,0 +1,34 @@
+{
+ "name": "lodash",
+ "version": "0.7.0",
+ "description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.",
+ "homepage": "http://lodash.com",
+ "main": [
+ "./lodash.js",
+ "./lodash.min.js"
+ ],
+ "keywords": [
+ "browser",
+ "client",
+ "functional",
+ "performance",
+ "server",
+ "speed",
+ "util"
+ ],
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://lodash.com/license"
+ }
+ ],
+ "author": {
+ "name": "John-David Dalton",
+ "email": "john.david.dalton@gmail.com",
+ "web": "http://allyoucanleet.com/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/bestiejs/lodash.git"
+ }
+}
diff --git a/doc/README.md b/doc/README.md
index d161acc63f..c48f6f141d 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,4 +1,4 @@
-# Lo-Dash v0.6.1
+# Lo-Dash v0.7.0
@@ -9,10 +9,13 @@
* [`_`](#_value)
* [`_.VERSION`](#_version)
* [`_.after`](#_aftern-func)
+* [`_.all`](#_everycollection--callbackidentity-thisarg)
+* [`_.any`](#_somecollection--callbackidentity-thisarg)
* [`_.bind`](#_bindfunc--thisarg-arg1-arg2-)
* [`_.bindAll`](#_bindallobject--methodname1-methodname2-)
* [`_.chain`](#_chainvalue)
-* [`_.clone`](#_clonevalue-deep--guard-stack-thorough)
+* [`_.clone`](#_clonevalue-deep--guard-data)
+* [`_.collect`](#_mapcollection--callbackidentity-thisarg)
* [`_.compact`](#_compactarray)
* [`_.compose`](#_composefunc1-func2-)
* [`_.contains`](#_containscollection-target)
@@ -21,8 +24,10 @@
* [`_.defaults`](#_defaultsobject--default1-default2-)
* [`_.defer`](#_deferfunc--arg1-arg2-)
* [`_.delay`](#_delayfunc-wait--arg1-arg2-)
+* [`_.detect`](#_findcollection-callback--thisarg)
* [`_.difference`](#_differencearray--array1-array2-)
-* [`_.drop`](#_dropobject-callback-prop1-prop2--thisarg)
+* [`_.drop`](#_restarray--n-guard)
+* [`_.each`](#_foreachcollection-callback--thisarg)
* [`_.escape`](#_escapestring)
* [`_.every`](#_everycollection--callbackidentity-thisarg)
* [`_.extend`](#_extendobject--source1-source2-)
@@ -30,16 +35,22 @@
* [`_.find`](#_findcollection-callback--thisarg)
* [`_.first`](#_firstarray--n-guard)
* [`_.flatten`](#_flattenarray-shallow)
+* [`_.foldl`](#_reducecollection-callback--accumulator-thisarg)
+* [`_.foldr`](#_reducerightcollection-callback--accumulator-thisarg)
* [`_.forEach`](#_foreachcollection-callback--thisarg)
* [`_.forIn`](#_forinobject-callback--thisarg)
* [`_.forOwn`](#_forownobject-callback--thisarg)
* [`_.functions`](#_functionsobject)
* [`_.groupBy`](#_groupbycollection-callbackproperty--thisarg)
* [`_.has`](#_hasobject-property)
+* [`_.head`](#_firstarray--n-guard)
* [`_.identity`](#_identityvalue)
+* [`_.include`](#_containscollection-target)
* [`_.indexOf`](#_indexofarray-value--fromindex0)
* [`_.initial`](#_initialarray--n-guard)
+* [`_.inject`](#_reducecollection-callback--accumulator-thisarg)
* [`_.intersection`](#_intersectionarray1-array2-)
+* [`_.invert`](#_invertobject)
* [`_.invoke`](#_invokecollection-methodname--arg1-arg2-)
* [`_.isArguments`](#_isargumentsvalue)
* [`_.isArray`](#_isarrayvalue)
@@ -47,7 +58,7 @@
* [`_.isDate`](#_isdatevalue)
* [`_.isElement`](#_iselementvalue)
* [`_.isEmpty`](#_isemptyvalue)
-* [`_.isEqual`](#_isequala-b--stack-thorough)
+* [`_.isEqual`](#_isequala-b--data)
* [`_.isFinite`](#_isfinitevalue)
* [`_.isFunction`](#_isfunctionvalue)
* [`_.isNaN`](#_isnanvalue)
@@ -63,25 +74,33 @@
* [`_.map`](#_mapcollection--callbackidentity-thisarg)
* [`_.max`](#_maxarray--callback-thisarg)
* [`_.memoize`](#_memoizefunc--resolver)
-* [`_.merge`](#_mergeobject--source1-source2--indicator-stack)
+* [`_.merge`](#_mergeobject--source1-source2--indicator-data)
+* [`_.methods`](#_functionsobject)
* [`_.min`](#_minarray--callback-thisarg)
* [`_.mixin`](#_mixinobject)
* [`_.noConflict`](#_noconflict)
+* [`_.object`](#_objectkeys--values)
+* [`_.omit`](#_omitobject-callback-prop1-prop2--thisarg)
* [`_.once`](#_oncefunc)
+* [`_.pairs`](#_pairsobject)
* [`_.partial`](#_partialfunc--arg1-arg2-)
* [`_.pick`](#_pickobject-callback-prop1-prop2--thisarg)
* [`_.pluck`](#_pluckcollection-property)
+* [`_.random`](#_randommin-max)
* [`_.range`](#_rangestart0-end--step1)
* [`_.reduce`](#_reducecollection-callback--accumulator-thisarg)
* [`_.reduceRight`](#_reducerightcollection-callback--accumulator-thisarg)
* [`_.reject`](#_rejectcollection--callbackidentity-thisarg)
* [`_.rest`](#_restarray--n-guard)
* [`_.result`](#_resultobject-property)
+* [`_.select`](#_filtercollection--callbackidentity-thisarg)
* [`_.shuffle`](#_shufflearray)
-* [`_.size`](#_sizevalue)
+* [`_.size`](#_sizecollection)
* [`_.some`](#_somecollection--callbackidentity-thisarg)
* [`_.sortBy`](#_sortbycollection-callbackproperty--thisarg)
* [`_.sortedIndex`](#_sortedindexarray-value--callbackidentity-thisarg)
+* [`_.tail`](#_restarray--n-guard)
+* [`_.take`](#_firstarray--n-guard)
* [`_.tap`](#_tapvalue-interceptor)
* [`_.template`](#_templatetext-data-options)
* [`_.throttle`](#_throttlefunc-wait)
@@ -90,13 +109,13 @@
* [`_.unescape`](#_unescapestring)
* [`_.union`](#_unionarray1-array2-)
* [`_.uniq`](#_uniqarray--issortedfalse-callbackidentity-thisarg)
+* [`_.unique`](#_uniqarray--issortedfalse-callbackidentity-thisarg)
* [`_.uniqueId`](#_uniqueidprefix)
* [`_.values`](#_valuesobject)
* [`_.where`](#_wherecollection-properties)
* [`_.without`](#_withoutarray--value1-value2-)
* [`_.wrap`](#_wrapvalue-wrapper)
* [`_.zip`](#_ziparray1-array2-)
-* [`_.zipObject`](#_zipobjectkeys--values)
@@ -122,14 +141,6 @@
-
-
-## ``
-* [``](#)
-
-
-
-
@@ -143,7 +154,7 @@
### `_(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L292 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L297 "View in source") [Ⓣ][1]
The `lodash` function.
@@ -161,7 +172,7 @@ The `lodash` function.
### `_.VERSION`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4171 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4260 "View in source") [Ⓣ][1]
*(String)*: The semantic version number.
@@ -173,7 +184,7 @@ The `lodash` function.
### `_.after(n, func)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3240 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3297 "View in source") [Ⓣ][1]
Creates a new function that is restricted to executing only after it is called `n` times.
@@ -201,7 +212,7 @@ _.forEach(notes, function(note) {
### `_.bind(func [, thisArg, arg1, arg2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3294 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3351 "View in source") [Ⓣ][1]
Creates a new function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those passed to the bound function. Lazy defined methods may be bound by passing the object they are bound to as `func` and the method name as `thisArg`.
@@ -252,7 +263,7 @@ func();
### `_.bindAll(object [, methodName1, methodName2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3364 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3421 "View in source") [Ⓣ][1]
Binds methods on `object` to `object`, overwriting the existing method. If no method names are provided, all the function properties of `object` will be bound.
@@ -283,7 +294,7 @@ jQuery('#lodash_button').on('click', buttonView.onClick);
### `_.chain(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4096 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4185 "View in source") [Ⓣ][1]
Wraps the value in a `lodash` wrapper object.
@@ -316,8 +327,8 @@ var youngest = _.chain(stooges)
-### `_.clone(value, deep [, guard, stack=[]], thorough)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1070 "View in source") [Ⓣ][1]
+### `_.clone(value, deep [, guard, data={}])`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1089 "View in source") [Ⓣ][1]
Creates a clone of `value`. If `deep` is `true`, all nested objects will also be cloned otherwise they will be assigned by reference. If a value has a `clone` method it will be used to perform the clone. Functions, DOM nodes, `arguments` objects, and objects created by constructors other than `Object` are **not** cloned unless they have a custom `clone` method.
@@ -325,8 +336,7 @@ Creates a clone of `value`. If `deep` is `true`, all nested objects will also be
1. `value` *(Mixed)*: The value to clone.
2. `deep` *(Boolean)*: A flag to indicate a deep clone.
3. `[guard]` *(Object)*: Internally used to allow this method to work with others like `_.map` without using their callback `index` argument for `deep`.
-4. `[stack=[]]` *(Array)*: Internally used to keep track of traversed objects to avoid circular references.
-5. `thorough` *(Object)*: Internally used to indicate whether or not to perform a more thorough clone of non-object values.
+4. `[data={}]` *(Object)*: Internally used to track traversed objects to avoid circular references and indicate whether to perform a more thorough clone of non-object values.
#### Returns
*(Mixed)*: Returns the cloned `value`.
@@ -359,7 +369,7 @@ shallow[0] === stooges[0];
### `_.compact(array)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2477 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2529 "View in source") [Ⓣ][1]
Creates a new array with all falsey values of `array` removed. The values `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
@@ -383,7 +393,7 @@ _.compact([0, 1, false, 2, '', 3]);
### `_.compose([func1, func2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3402 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3459 "View in source") [Ⓣ][1]
Creates a new function that is the composition of the passed functions, where each function consumes the return value of the function that follows. In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
@@ -410,10 +420,13 @@ welcome('moe');
### `_.contains(collection, target)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1961 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1985 "View in source") [Ⓣ][1]
Checks if a given `target` element is present in a `collection` using strict equality for comparisons, i.e. `===`.
+#### Aliases
+*include*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `target` *(Mixed)*: The value to check for.
@@ -441,7 +454,7 @@ _.contains('curly', 'ur');
### `_.countBy(collection, callback|property [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1997 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2021 "View in source") [Ⓣ][1]
Creates an object composed of keys returned from running each element of `collection` through a `callback`. The corresponding value of each key is the number of times the key was returned by `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. The `callback` argument may also be the name of a property to count by *(e.g. 'length')*.
@@ -473,7 +486,7 @@ _.countBy(['one', 'two', 'three'], 'length');
### `_.debounce(func, wait, immediate)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3435 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3492 "View in source") [Ⓣ][1]
Creates a new function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. Pass `true` for `immediate` to cause debounce to invoke `func` on the leading, instead of the trailing, edge of the `wait` timeout. Subsequent calls to the debounced function will return the result of the last `func` call.
@@ -499,7 +512,7 @@ jQuery(window).on('resize', lazyLayout);
### `_.defaults(object [, default1, default2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1171 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1194 "View in source") [Ⓣ][1]
Assigns enumerable properties of the default object(s) to the `destination` object for all `destination` properties that resolve to `null`/`undefined`. Once a property is set, additional defaults of the same property will be ignored.
@@ -525,7 +538,7 @@ _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
### `_.defer(func [, arg1, arg2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3500 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3557 "View in source") [Ⓣ][1]
Defers executing the `func` function until the current call stack has cleared. Additional arguments will be passed to `func` when it is invoked.
@@ -550,7 +563,7 @@ _.defer(function() { alert('deferred'); });
### `_.delay(func, wait [, arg1, arg2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3480 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3537 "View in source") [Ⓣ][1]
Executes the `func` function after `wait` milliseconds. Additional arguments will be passed to `func` when it is invoked.
@@ -577,7 +590,7 @@ _.delay(log, 1000, 'logged later');
### `_.difference(array [, array1, array2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2509 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2561 "View in source") [Ⓣ][1]
Creates a new array of `array` elements not present in the other arrays using strict equality for comparisons, i.e. `===`.
@@ -599,41 +612,10 @@ _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
-
-
-### `_.drop(object, callback|[prop1, prop2, ..., thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1201 "View in source") [Ⓣ][1]
-
-Creates a shallow clone of `object` excluding the specified properties. Property names may be specified as individual arguments or as arrays of property names. If `callback` is passed, it will be executed for each property in the `object`, dropping the properties `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*.
-
-#### Arguments
-1. `object` *(Object)*: The source object.
-2. `callback|[prop1, prop2, ...]` *(Function|String)*: The properties to drop or the function called per iteration.
-3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
-
-#### Returns
-*(Object)*: Returns an object without the dropped properties.
-
-#### Example
-```js
-_.drop({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
-// => { 'name': 'moe', 'age': 40 }
-
-_.drop({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
- return key.charAt(0) == '_';
-});
-// => { 'name': 'moe' }
-```
-
-* * *
-
-
-
-
### `_.escape(string)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3697 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3754 "View in source") [Ⓣ][1]
Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding HTML entities.
@@ -657,10 +639,13 @@ _.escape('Moe, Larry & Curly');
### `_.every(collection [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2017 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2041 "View in source") [Ⓣ][1]
Checks if the `callback` returns a truthy value for **all** elements of a `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
+#### Aliases
+*all*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `[callback=identity]` *(Function)*: The function called per iteration.
@@ -683,7 +668,7 @@ _.every([true, 1, null, 'yes'], Boolean);
### `_.extend(object [, source1, source2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1219 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1214 "View in source") [Ⓣ][1]
Assigns enumerable properties of the source object(s) to the `destination` object. Subsequent sources will overwrite propery assignments of previous sources.
@@ -708,10 +693,13 @@ _.extend({ 'name': 'moe' }, { 'age': 40 });
### `_.filter(collection [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2037 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2061 "View in source") [Ⓣ][1]
Examines each element in a `collection`, returning an array of all elements the `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
+#### Aliases
+*select*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `[callback=identity]` *(Function)*: The function called per iteration.
@@ -734,10 +722,13 @@ var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; })
### `_.find(collection, callback [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2058 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2082 "View in source") [Ⓣ][1]
Examines each element in a `collection`, returning the first one the `callback` returns truthy for. The function returns as soon as it finds an acceptable element, and does not iterate over the entire `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
+#### Aliases
+*detect*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `callback` *(Function)*: The function called per iteration.
@@ -760,10 +751,13 @@ var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
### `_.first(array [, n, guard])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2546 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2598 "View in source") [Ⓣ][1]
Gets the first element of the `array`. Pass `n` to return the first `n` elements of the `array`.
+#### Aliases
+*head, take*
+
#### Arguments
1. `array` *(Array)*: The array to query.
2. `[n]` *(Number)*: The number of elements to return.
@@ -786,7 +780,7 @@ _.first([5, 4, 3, 2, 1]);
### `_.flatten(array, shallow)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2570 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2622 "View in source") [Ⓣ][1]
Flattens a nested array *(the nesting can be to any depth)*. If `shallow` is truthy, `array` will only be flattened a single level.
@@ -814,10 +808,13 @@ _.flatten([1, [2], [3, [[4]]]], true);
### `_.forEach(collection, callback [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2085 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2109 "View in source") [Ⓣ][1]
Iterates over a `collection`, executing the `callback` for each element in the `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. Callbacks may exit iteration early by explicitly returning `false`.
+#### Aliases
+*each*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `callback` *(Function)*: The function called per iteration.
@@ -843,7 +840,7 @@ _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
### `_.forIn(object, callback [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1249 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1244 "View in source") [Ⓣ][1]
Iterates over `object`'s own and inherited enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`.
@@ -879,7 +876,7 @@ _.forIn(new Dog('Dagny'), function(value, key) {
### `_.forOwn(object, callback [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1273 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1268 "View in source") [Ⓣ][1]
Iterates over `object`'s own enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*. Callbacks may exit iteration early by explicitly returning `false`.
@@ -907,10 +904,13 @@ _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
### `_.functions(object)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1290 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1285 "View in source") [Ⓣ][1]
Creates a sorted array of all enumerable properties, own and inherited, of `object` that have function values.
+#### Aliases
+*methods*
+
#### Arguments
1. `object` *(Object)*: The object to inspect.
@@ -931,7 +931,7 @@ _.functions(_);
### `_.groupBy(collection, callback|property [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2113 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2137 "View in source") [Ⓣ][1]
Creates an object composed of keys returned from running each element of `collection` through a `callback`. The corresponding value of each key is an array of elements passed to `callback` that returned the key. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. The `callback` argument may also be the name of a property to count by *(e.g. 'length')*.
@@ -963,7 +963,7 @@ _.groupBy(['one', 'two', 'three'], 'length');
### `_.has(object, property)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1313 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1308 "View in source") [Ⓣ][1]
Checks if the specified object `property` exists and is a direct property, instead of an inherited property.
@@ -988,7 +988,7 @@ _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
### `_.identity(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3717 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3774 "View in source") [Ⓣ][1]
This function returns the first argument passed to it. Note: It is used throughout Lo-Dash as a default callback.
@@ -1013,7 +1013,7 @@ moe === _.identity(moe);
### `_.indexOf(array, value [, fromIndex=0])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2614 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2666 "View in source") [Ⓣ][1]
Gets the index at which the first occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `isSorted` will run a faster binary search.
@@ -1045,7 +1045,7 @@ _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
### `_.initial(array [, n, guard])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2654 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2706 "View in source") [Ⓣ][1]
Gets all but the last element of `array`. Pass `n` to exclude the last `n` elements from the result.
@@ -1071,7 +1071,7 @@ _.initial([3, 2, 1]);
### `_.intersection([array1, array2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2676 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2728 "View in source") [Ⓣ][1]
Computes the intersection of all the passed-in arrays using strict equality for comparisons, i.e. `===`.
@@ -1092,10 +1092,34 @@ _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+
+
+### `_.invert(object)`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1325 "View in source") [Ⓣ][1]
+
+Creates an object composed of the inverted keys and values of the given `object`.
+
+#### Arguments
+1. `object` *(Object)*: The object to invert.
+
+#### Returns
+*(Object)*: Returns the created inverted object.
+
+#### Example
+```js
+_.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
+// => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
+```
+
+* * *
+
+
+
+
### `_.invoke(collection, methodName [, arg1, arg2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2141 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2165 "View in source") [Ⓣ][1]
Invokes the method named by `methodName` on each element in the `collection`. Additional arguments will be passed to each invoked method. If `methodName` is a function it will be invoked for, and `this` bound to, each element in the `collection`.
@@ -1124,7 +1148,7 @@ _.invoke([123, 456], String.prototype.split, '');
### `_.isArguments(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L910 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L917 "View in source") [Ⓣ][1]
Checks if `value` is an `arguments` object.
@@ -1151,7 +1175,7 @@ _.isArguments([1, 2, 3]);
### `_.isArray(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L936 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L943 "View in source") [Ⓣ][1]
Checks if `value` is an array.
@@ -1178,7 +1202,7 @@ _.isArray([1, 2, 3]);
### `_.isBoolean(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1330 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1344 "View in source") [Ⓣ][1]
Checks if `value` is a boolean *(`true` or `false`)* value.
@@ -1202,7 +1226,7 @@ _.isBoolean(null);
### `_.isDate(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1347 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1361 "View in source") [Ⓣ][1]
Checks if `value` is a date.
@@ -1226,7 +1250,7 @@ _.isDate(new Date);
### `_.isElement(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1364 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1378 "View in source") [Ⓣ][1]
Checks if `value` is a DOM element.
@@ -1250,7 +1274,7 @@ _.isElement(document.body);
### `_.isEmpty(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1389 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1403 "View in source") [Ⓣ][1]
Checks if `value` is empty. Arrays, strings, or `arguments` objects with a length of `0` and objects with no own enumerable properties are considered "empty".
@@ -1279,16 +1303,15 @@ _.isEmpty('');
-### `_.isEqual(a, b [, stack=[]], thorough)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1431 "View in source") [Ⓣ][1]
+### `_.isEqual(a, b [, data={}])`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1444 "View in source") [Ⓣ][1]
Performs a deep comparison between two values to determine if they are equivalent to each other. If a value has an `isEqual` method it will be used to perform the comparison.
#### Arguments
1. `a` *(Mixed)*: The value to compare.
2. `b` *(Mixed)*: The other value to compare.
-3. `[stack=[]]` *(Array)*: Internally used to keep track of traversed objects to avoid circular references.
-4. `thorough` *(Object)*: Internally used to indicate whether or not to perform a more thorough comparison of non-object values.
+3. `[data={}]` *(Object)*: Internally used track traversed objects to avoid circular references and indicate whether to perform a more thorough comparison of non-object values.
#### Returns
*(Boolean)*: Returns `true` if the values are equvalent, else `false`.
@@ -1313,7 +1336,7 @@ _.isEqual(moe, clone);
### `_.isFinite(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1604 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1619 "View in source") [Ⓣ][1]
Checks if `value` is a finite number. Note: This is not the same as native `isFinite`, which will return true for booleans and other values. See http://es5.github.com/#x15.1.2.5.
@@ -1343,7 +1366,7 @@ _.isFinite(Infinity);
### `_.isFunction(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L953 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L960 "View in source") [Ⓣ][1]
Checks if `value` is a function.
@@ -1367,7 +1390,7 @@ _.isFunction(''.concat);
### `_.isNaN(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1659 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1674 "View in source") [Ⓣ][1]
Checks if `value` is `NaN`. Note: This is not the same as native `isNaN`, which will return true for `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
@@ -1400,7 +1423,7 @@ _.isNaN(undefined);
### `_.isNull(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1682 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1697 "View in source") [Ⓣ][1]
Checks if `value` is `null`.
@@ -1427,7 +1450,7 @@ _.isNull(undefined);
### `_.isNumber(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1699 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1714 "View in source") [Ⓣ][1]
Checks if `value` is a number.
@@ -1451,7 +1474,7 @@ _.isNumber(8.4 * 5;
### `_.isObject(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1625 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1640 "View in source") [Ⓣ][1]
Checks if `value` is the language type of Object. *(e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)*
@@ -1478,7 +1501,7 @@ _.isObject(1);
### `_.isRegExp(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1716 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1731 "View in source") [Ⓣ][1]
Checks if `value` is a regular expression.
@@ -1502,7 +1525,7 @@ _.isRegExp(/moe/);
### `_.isString(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1733 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1748 "View in source") [Ⓣ][1]
Checks if `value` is a string.
@@ -1526,7 +1549,7 @@ _.isString('moe');
### `_.isUndefined(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1751 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1766 "View in source") [Ⓣ][1]
Checks if `value` is `undefined`.
@@ -1550,7 +1573,7 @@ _.isUndefined(void 0);
### `_.keys(object)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1768 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1783 "View in source") [Ⓣ][1]
Creates an array composed of the own enumerable property names of `object`.
@@ -1574,7 +1597,7 @@ _.keys({ 'one': 1, 'two': 2, 'three': 3 });
### `_.last(array [, n, guard])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2719 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2771 "View in source") [Ⓣ][1]
Gets the last element of the `array`. Pass `n` to return the lasy `n` elementsvof the `array`.
@@ -1600,7 +1623,7 @@ _.last([3, 2, 1]);
### `_.lastIndexOf(array, value [, fromIndex=array.length-1])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2745 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2797 "View in source") [Ⓣ][1]
Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`.
@@ -1629,10 +1652,13 @@ _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
### `_.map(collection [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2176 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2200 "View in source") [Ⓣ][1]
Creates a new array of values by running each element in the `collection` through a `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
+#### Aliases
+*collect*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `[callback=identity]` *(Function)*: The function called per iteration.
@@ -1658,7 +1684,7 @@ _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
### `_.max(array [, callback, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2785 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2837 "View in source") [Ⓣ][1]
Retrieves the maximum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
@@ -1690,7 +1716,7 @@ _.max(stooges, function(stooge) { return stooge.age; });
### `_.memoize(func [, resolver])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3523 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3580 "View in source") [Ⓣ][1]
Creates a new function that memoizes the result of `func`. If `resolver` is passed, it will be used to determine the cache key for storing the result based on the arguments passed to the memoized function. By default, the first argument passed to the memoized function is used as the cache key.
@@ -1715,8 +1741,8 @@ var fibonacci = _.memoize(function(n) {
-### `_.merge(object [, source1, source2, ..., indicator, stack=[]])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1810 "View in source") [Ⓣ][1]
+### `_.merge(object [, source1, source2, ..., indicator, data={}])`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1825 "View in source") [Ⓣ][1]
Merges enumerable properties of the source object(s) into the `destination` object. Subsequent sources will overwrite propery assignments of previous sources.
@@ -1724,7 +1750,7 @@ Merges enumerable properties of the source object(s) into the `destination` obje
1. `object` *(Object)*: The destination object.
2. `[source1, source2, ...]` *(Object)*: The source objects.
3. `[indicator]` *(Object)*: Internally used to indicate that the `stack` argument is an array of traversed objects instead of another source object.
-4. `[stack=[]]` *(Array)*: Internally used to keep track of traversed objects to avoid circular references.
+4. `[data={}]` *(Object)*: Internally used to track traversed objects to avoid circular references.
#### Returns
*(Object)*: Returns the destination object.
@@ -1753,7 +1779,7 @@ _.merge(stooges, ages);
### `_.min(array [, callback, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2835 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2887 "View in source") [Ⓣ][1]
Retrieves the minimum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
@@ -1779,7 +1805,7 @@ _.min([10, 5, 100, 2, 1000]);
### `_.mixin(object)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3743 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3800 "View in source") [Ⓣ][1]
Adds functions properties of `object` to the `lodash` function and chainable wrapper.
@@ -1809,7 +1835,7 @@ _('curly').capitalize();
### `_.noConflict()`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3774 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3831 "View in source") [Ⓣ][1]
Reverts the '_' variable to its previous value and returns a reference to the `lodash` function.
@@ -1826,10 +1852,66 @@ var lodash = _.noConflict();
+
+
+### `_.object(keys [, values=[]])`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2936 "View in source") [Ⓣ][1]
+
+Creates an object composed from arrays of `keys` and `values`. Pass either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or two arrays, one of `keys` and one of corresponding `values`.
+
+#### Arguments
+1. `keys` *(Array)*: The array of keys.
+2. `[values=[]]` *(Array)*: The array of values.
+
+#### Returns
+*(Object)*: Returns an object composed of the given keys and corresponding values.
+
+#### Example
+```js
+_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
+// => { 'moe': 30, 'larry': 40, 'curly': 50 }
+```
+
+* * *
+
+
+
+
+
+
+### `_.omit(object, callback|[prop1, prop2, ..., thisArg])`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1878 "View in source") [Ⓣ][1]
+
+Creates a shallow clone of `object` excluding the specified properties. Property names may be specified as individual arguments or as arrays of property names. If `callback` is passed, it will be executed for each property in the `object`, omitting the properties `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*.
+
+#### Arguments
+1. `object` *(Object)*: The source object.
+2. `callback|[prop1, prop2, ...]` *(Function|String)*: The properties to omit or the function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Object)*: Returns an object without the omitted properties.
+
+#### Example
+```js
+_.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
+// => { 'name': 'moe', 'age': 40 }
+
+_.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
+ return key.charAt(0) == '_';
+});
+// => { 'name': 'moe' }
+```
+
+* * *
+
+
+
+
### `_.once(func)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3549 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3606 "View in source") [Ⓣ][1]
Creates a new function that is restricted to one execution. Repeat calls to the function will return the value of the first call.
@@ -1852,10 +1934,34 @@ initialize();
+
+
+### `_.pairs(object)`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1894 "View in source") [Ⓣ][1]
+
+Creates a two dimensional array of the given object's key-value pairs, i.e. `[[key1, value1], [key2, value2]]`.
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns new array of key-value pairs.
+
+#### Example
+```js
+_.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
+// => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
+```
+
+* * *
+
+
+
+
### `_.partial(func [, arg1, arg2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3584 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3641 "View in source") [Ⓣ][1]
Creates a new function that, when called, invokes `func` with any additional `partial` arguments prepended to those passed to the new function. This method is similar `bind`, except it does **not** alter the `this` binding.
@@ -1882,7 +1988,7 @@ hi('moe');
### `_.pick(object, callback|[prop1, prop2, ..., thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1862 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1925 "View in source") [Ⓣ][1]
Creates a shallow clone of `object` composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names. If `callback` is passed, it will be executed for each property in the `object`, picking the properties `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*.
@@ -1913,7 +2019,7 @@ _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(va
### `_.pluck(collection, property)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2199 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2223 "View in source") [Ⓣ][1]
Retrieves the value of a specified property from all elements in the `collection`.
@@ -1941,10 +2047,41 @@ _.pluck(stooges, 'name');
+
+
+### `_.random(min, max)`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3858 "View in source") [Ⓣ][1]
+
+Produces a random number between `min` and `max` *(inclusive)*. If only one argument is passed, a number between `0` and the given number will be returned. If no arguments are passed `_.random` will act as `Math.random`.
+
+#### Arguments
+1. `min` *(Number)*: The minimum possible value.
+2. `max` *(Number)*: The maximum possible value.
+
+#### Returns
+*(Number)*: Returns a random number.
+
+#### Example
+```js
+_.random(0, 5);
+// => a number between 1 and 5
+
+_.random(5);
+// => also a number between 1 and 5
+
+_.random();
+// => an integer between 0 and less than 1
+```
+
+* * *
+
+
+
+
### `_.range([start=0], end [, step=1])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2896 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2983 "View in source") [Ⓣ][1]
Creates an array of numbers *(positive and/or negative)* progressing from `start` up to but not including `stop`. This method is a port of Python's `range()` function. See http://docs.python.org/library/functions.html#range.
@@ -1982,10 +2119,13 @@ _.range(0);
### `_.reduce(collection, callback [, accumulator, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2227 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2251 "View in source") [Ⓣ][1]
Boils down a `collection` to a single value. The initial state of the reduction is `accumulator` and each successive step of it should be returned by the `callback`. The `callback` is bound to `thisArg` and invoked with `4` arguments; for arrays they are *(accumulator, value, index|key, collection)*.
+#### Aliases
+*foldl, inject*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `callback` *(Function)*: The function called per iteration.
@@ -2009,10 +2149,13 @@ var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
### `_.reduceRight(collection, callback [, accumulator, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2264 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2288 "View in source") [Ⓣ][1]
The right-associative version of `_.reduce`.
+#### Aliases
+*foldr*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `callback` *(Function)*: The function called per iteration.
@@ -2037,7 +2180,7 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
### `_.reject(collection [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2320 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2344 "View in source") [Ⓣ][1]
The opposite of `_.filter`, this method returns the values of a `collection` that `callback` does **not** return truthy for.
@@ -2063,10 +2206,13 @@ var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
### `_.rest(array [, n, guard])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2935 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3022 "View in source") [Ⓣ][1]
The opposite of `_.initial`, this method gets all but the first value of `array`. Pass `n` to exclude the first `n` values from the result.
+#### Aliases
+*drop, tail*
+
#### Arguments
1. `array` *(Array)*: The array to query.
2. `[n]` *(Number)*: The number of elements to return.
@@ -2089,7 +2235,7 @@ _.rest([3, 2, 1]);
### `_.result(object, property)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3806 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3897 "View in source") [Ⓣ][1]
Resolves the value of `property` on `object`. If `property` is a function it will be invoked and its result returned, else the property value is returned. If `object` is falsey, then `null` is returned.
@@ -2124,7 +2270,7 @@ _.result(object, 'stuff');
### `_.shuffle(array)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2956 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3043 "View in source") [Ⓣ][1]
Creates a new array of shuffled `array` values, using a version of the Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
@@ -2147,16 +2293,16 @@ _.shuffle([1, 2, 3, 4, 5, 6]);
-### `_.size(value)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1900 "View in source") [Ⓣ][1]
+### `_.size(collection)`
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2368 "View in source") [Ⓣ][1]
-Gets the size of `value` by returning `value.length` if `value` is an array, string, or `arguments` object. If `value` is an object, size is determined by returning the number of own enumerable properties it has.
+Gets the size of the `collection` by returning `collection.length` for arrays and array-like objects or the number of own enumerable properties for objects.
#### Arguments
-1. `value` *(Array|Object|String)*: The value to inspect.
+1. `collection` *(Array|Object|String)*: The collection to inspect.
#### Returns
-*(Number)*: Returns `value.length` or number of own enumerable properties.
+*(Number)*: Returns `collection.length` or number of own enumerable properties.
#### Example
```js
@@ -2178,10 +2324,13 @@ _.size('curly');
### `_.some(collection [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2343 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2395 "View in source") [Ⓣ][1]
Checks if the `callback` returns a truthy value for **any** element of a `collection`. The function returns as soon as it finds passing value, and does not iterate over the entire `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
+#### Aliases
+*any*
+
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
2. `[callback=identity]` *(Function)*: The function called per iteration.
@@ -2204,7 +2353,7 @@ _.some([null, 0, 'yes', false]);
### `_.sortBy(collection, callback|property [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2373 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2425 "View in source") [Ⓣ][1]
Creates a new array, stable sorted in ascending order by the results of running each element of `collection` through a `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. The `callback` argument may also be the name of a property to sort by *(e.g. 'length')*.
@@ -2236,7 +2385,7 @@ _.sortBy(['larry', 'brendan', 'moe'], 'length');
### `_.sortedIndex(array, value [, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3008 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3095 "View in source") [Ⓣ][1]
Uses a binary search to determine the smallest index at which the `value` should be inserted into `array` in order to maintain the sort order of the sorted `array`. If `callback` is passed, it will be executed for `value` and each element in `array` to compute their sort ranking. The `callback` is bound to `thisArg` and invoked with `1` argument; *(value)*.
@@ -2277,7 +2426,7 @@ _.sortedIndex(['twenty', 'thirty', 'fourty'], 'thirty-five', function(word) {
### `_.tap(value, interceptor)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4123 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4212 "View in source") [Ⓣ][1]
Invokes `interceptor` with the `value` as the first argument, and then returns `value`. The purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
@@ -2307,7 +2456,7 @@ _.chain([1,2,3,200])
### `_.template(text, data, options)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3879 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3970 "View in source") [Ⓣ][1]
A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code. Note: In the development build `_.template` utilizes sourceURLs for easier debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page. See http://developer.chrome.com/trunk/extensions/sandboxingEval.html
@@ -2372,7 +2521,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\
### `_.throttle(func, wait)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3620 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3677 "View in source") [Ⓣ][1]
Creates a new function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. If the throttled function is invoked more than once during the `wait` timeout, `func` will also be called on the trailing edge of the timeout. Subsequent calls to the throttled function will return the result of the last `func` call.
@@ -2397,7 +2546,7 @@ jQuery(window).on('scroll', throttled);
### `_.times(n, callback [, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4021 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4110 "View in source") [Ⓣ][1]
Executes the `callback` function `n` times. The `callback` is bound to `thisArg` and invoked with `1` argument; *(index)*.
@@ -2408,11 +2557,11 @@ Executes the `callback` function `n` times. The `callback` is bound to `thisArg`
#### Example
```js
-_.times(3, function() { genie.grantWish(); });
-// => calls `genie.grantWish()` 3 times
+_.times(3, function(n) { genie.grantWish(n); });
+// => calls `genie.grantWish(n)` three times, passing `n` of `0`, `1`, and `2` respectively
-_.times(3, function() { this.grantWish(); }, genie);
-// => also calls `genie.grantWish()` 3 times
+_.times(3, function(n) { this.grantWish(n); }, genie);
+// => also calls `genie.grantWish(n)` three times
```
* * *
@@ -2423,7 +2572,7 @@ _.times(3, function() { this.grantWish(); }, genie);
### `_.toArray(collection)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2410 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2462 "View in source") [Ⓣ][1]
Converts the `collection`, to an array. Useful for converting the `arguments` object.
@@ -2447,7 +2596,7 @@ Converts the `collection`, to an array. Useful for converting the `arguments` ob
### `_.unescape(string)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4048 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4137 "View in source") [Ⓣ][1]
Converts the HTML entities `&`, `<`, `>`, `"`, and `'` in `string` to their corresponding characters.
@@ -2471,7 +2620,7 @@ _.unescape('Moe, Larry & Curly');
### `_.union([array1, array2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3049 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3136 "View in source") [Ⓣ][1]
Computes the union of the passed-in arrays using strict equality for comparisons, i.e. `===`.
@@ -2495,10 +2644,13 @@ _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
### `_.uniq(array [, isSorted=false, callback=identity, thisArg])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3093 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3180 "View in source") [Ⓣ][1]
Creates a duplicate-value-free version of the `array` using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `isSorted` will run a faster algorithm. If `callback` is passed, each element of `array` is passed through a callback` before uniqueness is computed. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
+#### Aliases
+*unique*
+
#### Arguments
1. `array` *(Array)*: The array to process.
2. `[isSorted=false]` *(Boolean)*: A flag to indicate that the `array` is already sorted.
@@ -2531,7 +2683,7 @@ _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
### `_.uniqueId([prefix])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4066 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4155 "View in source") [Ⓣ][1]
Generates a unique id. If `prefix` is passed, the id will be appended to it.
@@ -2555,7 +2707,7 @@ _.uniqueId('contact_');
### `_.values(object)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1931 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1955 "View in source") [Ⓣ][1]
Creates an array composed of the own enumerable property values of `object`.
@@ -2579,7 +2731,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 });
### `_.where(collection, properties)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2447 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2499 "View in source") [Ⓣ][1]
Examines each element in a `collection`, returning an array of all elements that contain the given `properties`.
@@ -2610,7 +2762,7 @@ _.where(stooges, { 'age': 40 });
### `_.without(array [, value1, value2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3142 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3229 "View in source") [Ⓣ][1]
Creates a new array with all occurrences of the passed values removed using strict equality for comparisons, i.e. `===`.
@@ -2635,7 +2787,7 @@ _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
### `_.wrap(value, wrapper)`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3671 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3728 "View in source") [Ⓣ][1]
Creates a new function that passes `value` to the `wrapper` function as its first argument. Additional arguments passed to the new function are appended to those passed to the `wrapper` function.
@@ -2664,7 +2816,7 @@ hello();
### `_.zip([array1, array2, ...])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3175 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3262 "View in source") [Ⓣ][1]
Groups the elements of each array at their corresponding indexes. Useful for separate data sources that are coordinated through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix in a similar fashion.
@@ -2685,31 +2837,6 @@ _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
-
-
-### `_.zipObject(keys [, values=[]])`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3204 "View in source") [Ⓣ][1]
-
-Creates an object composed from an array of `keys` and an array of `values`.
-
-#### Arguments
-1. `keys` *(Array)*: The array of keys.
-2. `[values=[]]` *(Array)*: The array of values.
-
-#### Returns
-*(Object)*: Returns an object composed of the given keys and corresponding values.
-
-#### Example
-```js
-_.zipObject(['moe', 'larry', 'curly'], [30, 40, 50]);
-// => { 'moe': 30, 'larry': 40, 'curly': 50 }
-```
-
-* * *
-
-
-
-
@@ -2720,7 +2847,7 @@ _.zipObject(['moe', 'larry', 'curly'], [30, 40, 50]);
### `_.prototype.chain()`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4141 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4230 "View in source") [Ⓣ][1]
Enables method chaining on the wrapper object.
@@ -2741,7 +2868,7 @@ _([1, 2, 3]).value();
### `_.prototype.value()`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4158 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L4247 "View in source") [Ⓣ][1]
Extracts the wrapped value.
@@ -2769,7 +2896,7 @@ _([1, 2, 3]).value();
### `_.templateSettings`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L321 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L326 "View in source") [Ⓣ][1]
*(Object)*: By default, the template delimiters used by Lo-Dash are similar to those in embedded Ruby *(ERB)*. Change the following template settings to use alternative delimiters.
@@ -2781,7 +2908,7 @@ _([1, 2, 3]).value();
### `_.templateSettings.escape`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L330 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L335 "View in source") [Ⓣ][1]
*(RegExp)*: Used to detect `data` property values to be HTML-escaped.
@@ -2793,7 +2920,7 @@ _([1, 2, 3]).value();
### `_.templateSettings.evaluate`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L339 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L344 "View in source") [Ⓣ][1]
*(RegExp)*: Used to detect code to be evaluated.
@@ -2805,7 +2932,7 @@ _([1, 2, 3]).value();
### `_.templateSettings.interpolate`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L348 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L353 "View in source") [Ⓣ][1]
*(RegExp)*: Used to detect `data` property values to inject.
@@ -2817,7 +2944,7 @@ _([1, 2, 3]).value();
### `_.templateSettings.variable`
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L357 "View in source") [Ⓣ][1]
+# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L362 "View in source") [Ⓣ][1]
*(String)*: Used to reference the data object in the template text.
@@ -2829,25 +2956,6 @@ _([1, 2, 3]).value();
-
-
-## ``
-
-
-
-### ``
-# [Ⓢ](https://github.com/bestiejs/lodash/blob/master/lodash.js#L218 "View in source") [Ⓣ][1]
-
-(Unknown): Detect if sourceURL syntax is usable without erroring: The JS engine in Adobe products, like InDesign, will throw a syntax error when it encounters a single line comment beginning with the `@` symbol. The JS engine in Narwhal will generate the function `function anonymous(){//}` and throw a syntax error. Avoid comments beginning `@` symbols in IE because they are part of its non-standard conditional compilation support. http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
-
-* * *
-
-
-
-
-
-
-
diff --git a/doc/parse.php b/doc/parse.php
index 4a29737e34..bde5d45f5f 100644
--- a/doc/parse.php
+++ b/doc/parse.php
@@ -21,7 +21,7 @@
// generate Markdown
$markdown = docdown(array(
'path' => '../' . $file,
- 'title' => 'Lo-Dash v0.6.1',
+ 'title' => 'Lo-Dash v0.7.0',
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
));
diff --git a/lodash.js b/lodash.js
index 8b5c88c095..142ac23876 100644
--- a/lodash.js
+++ b/lodash.js
@@ -1,5 +1,5 @@
/*!
- * Lo-Dash v0.6.1
+ * Lo-Dash v0.7.0
* Copyright 2012 John-David Dalton
* Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
*
@@ -54,7 +54,7 @@
var oldDash = window._;
/** Used to detect delimiter values that should be processed by `tokenizeEvaluate` */
- var reComplexDelimiter = /[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
+ var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
/** Used to match HTML entities */
var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g;
@@ -78,7 +78,7 @@
);
/** Used to match internally used tokens in template text */
- var reToken = /__token__(\d+)/g;
+ var reToken = /__token(\d+)__/g;
/** Used to match HTML characters */
var reUnescapedHtml = /[&<>"']/g;
@@ -96,7 +96,8 @@
var templateCounter = 0;
/** Used to replace template delimiters */
- var token = '__token__';
+ var tokenHead = '__token',
+ tokenFoot = '__';
/** Used to store tokenized template text snippets */
var tokenized = [];
@@ -111,9 +112,13 @@
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+ nativeFloor = Math.floor,
nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
nativeIsFinite = window.isFinite,
- nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys;
+ nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeRandom = Math.random;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
@@ -217,7 +222,7 @@
*/
try {
var useSourceURL = (Function('//@')(), !window.attachEvent);
- } catch(e){ }
+ } catch(e) { }
/** Used to identify object classifications that are array-like */
var arrayLikeClasses = {};
@@ -303,10 +308,10 @@
*/
function LoDash(value) {
// exit early if already wrapped
- if (value && value._wrapped) {
+ if (value && value.__wrapped__) {
return value;
}
- this._wrapped = value;
+ this.__wrapped__ = value;
}
/**
@@ -442,8 +447,8 @@
// else using a for-in loop
' <% } else { %>\n' +
' <%= objectBranch.beforeLoop %>;\n' +
- ' for (index in iteratee) {' +
- ' <% if (!hasDontEnumBug || useHas) { %>\n if (<%' +
+ ' for (index in iteratee) {<%' +
+ ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
' if (!hasDontEnumBug) { %>!(skipProto && index == \'prototype\')<% }' +
' if (!hasDontEnumBug && useHas) { %> && <% }' +
' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
@@ -516,25 +521,6 @@
'(hasOwnProperty.call(result, prop) ? result[prop]++ : result[prop] = 1)'
};
- /** Reusable iterator options for `drop` and `pick` */
- var dropIteratorOptions = {
- 'useHas': false,
- 'args': 'object, callback, thisArg',
- 'init': '{}',
- 'top':
- 'var isFunc = typeof callback == \'function\';\n' +
- 'if (!isFunc) {\n' +
- ' var props = concat.apply(ArrayProto, arguments)\n' +
- '} else if (thisArg) {\n' +
- ' callback = iteratorBind(callback, thisArg)\n' +
- '}',
- 'inLoop':
- 'if (isFunc\n' +
- ' ? !callback(value, index, object)\n' +
- ' : indexOf(props, index) < 0\n' +
- ') result[index] = value'
- };
-
/** Reusable iterator options for `every` and `some` */
var everyIteratorOptions = {
'init': 'true',
@@ -586,6 +572,25 @@
}
};
+ /** Reusable iterator options for `omit` and `pick` */
+ var omitIteratorOptions = {
+ 'useHas': false,
+ 'args': 'object, callback, thisArg',
+ 'init': '{}',
+ 'top':
+ 'var isFunc = typeof callback == \'function\';\n' +
+ 'if (!isFunc) {\n' +
+ ' var props = concat.apply(ArrayProto, arguments)\n' +
+ '} else if (thisArg) {\n' +
+ ' callback = iteratorBind(callback, thisArg)\n' +
+ '}',
+ 'inLoop':
+ 'if (isFunc\n' +
+ ' ? !callback(value, index, object)\n' +
+ ' : indexOf(props, index) < 0\n' +
+ ') result[index] = value'
+ };
+
/*--------------------------------------------------------------------------*/
/**
@@ -752,15 +757,17 @@
a = a.criteria;
b = b.criteria;
- if (a === undefined) {
- return 1;
- }
- if (b === undefined) {
- return -1;
- }
// ensure a stable sort in V8 and other engines
// http://code.google.com/p/v8/issues/detail?id=90
- return a < b ? -1 : a > b ? 1 : ai < bi ? -1 : 1;
+ if (a !== b) {
+ if (a > b || a === undefined) {
+ return 1;
+ }
+ if (a < b || b === undefined) {
+ return -1;
+ }
+ }
+ return ai < bi ? -1 : 1;
}
/**
@@ -836,7 +843,7 @@
}
var index = tokenized.length;
tokenized[index] = "' +\n__e(" + value + ") +\n'";
- return token + index;
+ return tokenHead + index + tokenFoot;
}
/**
@@ -854,7 +861,7 @@
if (evaluateValue) {
var index = tokenized.length;
tokenized[index] = "';\n" + evaluateValue + ";\n__p += '";
- return token + index;
+ return tokenHead + index + tokenFoot;
}
return escapeValue
? tokenizeEscape(null, escapeValue)
@@ -875,7 +882,7 @@
}
var index = tokenized.length;
tokenized[index] = "' +\n((__t = (" + value + ")) == null ? '' : __t) +\n'";
- return token + index;
+ return tokenHead + index + tokenFoot;
}
/**
@@ -961,58 +968,71 @@
}
/**
- * Checks if a given `value` is an object created by the `Object` constructor
- * assuming objects created by the `Object` constructor have no inherited
- * enumerable properties and that there are no `Object.prototype` extensions.
+ * A fallback implementation of `isPlainObject` that checks if a given `value`
+ * is an object created by the `Object` constructor, assuming objects created
+ * by the `Object` constructor have no inherited enumerable properties and that
+ * there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
* `arguments` objects.
- * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object,
- * else `false`.
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
*/
- function isPlainObject(value, skipArgsCheck) {
- return value
- ? value == ObjectProto || (value.__proto__ == ObjectProto && (skipArgsCheck || !isArguments(value)))
- : false;
- }
- // fallback for IE
- if (!isPlainObject(objectTypes)) {
- isPlainObject = function(value, skipArgsCheck) {
- // avoid non-objects and false positives for `arguments` objects
- var result = false;
- if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
- return result;
- }
- // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
- // methods that are `typeof` "string" and still can coerce nodes to strings.
- // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
- var ctor = value.constructor;
- if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
- (!isFunction(ctor) || ctor instanceof ctor)) {
- // IE < 9 iterates inherited properties before own properties. If the first
- // iterated property is an object's own property then there are no inherited
- // enumerable properties.
- if (iteratesOwnLast) {
- forIn(value, function(objValue, objKey) {
- result = !hasOwnProperty.call(value, objKey);
- return false;
- });
- return result === false;
- }
- // In most environments an object's own properties are iterated before
- // its inherited properties. If the last iterated property is an object's
- // own property then there are no inherited enumerable properties.
- forIn(value, function(objValue, objKey) {
- result = objKey;
+ function isPlainFallback(value, skipArgsCheck) {
+ // avoid non-objects and false positives for `arguments` objects
+ var result = false;
+ if (!(value && typeof value == 'object') || (!skipArgsCheck && isArguments(value))) {
+ return result;
+ }
+ // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+ // methods that are `typeof` "string" and still can coerce nodes to strings.
+ // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
+ var ctor = value.constructor;
+ if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
+ (!isFunction(ctor) || ctor instanceof ctor)) {
+ // IE < 9 iterates inherited properties before own properties. If the first
+ // iterated property is an object's own property then there are no inherited
+ // enumerable properties.
+ if (iteratesOwnLast) {
+ forIn(value, function(value, key, object) {
+ result = !hasOwnProperty.call(object, key);
+ return false;
});
- return result === false || hasOwnProperty.call(value, result);
+ return result === false;
}
- return result;
- };
+ // In most environments an object's own properties are iterated before
+ // its inherited properties. If the last iterated property is an object's
+ // own property then there are no inherited enumerable properties.
+ forIn(value, function(value, key) {
+ result = key;
+ });
+ return result === false || hasOwnProperty.call(value, result);
+ }
+ return result;
}
+ /**
+ * Checks if a given `value` is an object created by the `Object` constructor.
+ *
+ * @private
+ * @param {Mixed} value The value to check.
+ * @param {Boolean} [skipArgsCheck=false] Internally used to skip checks for
+ * `arguments` objects.
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
+ */
+ var isPlainObject = objectTypes.__proto__ != ObjectProto ? isPlainFallback : function(value, skipArgsCheck) {
+ if (!value) {
+ return false;
+ }
+ var valueOf = value.valueOf,
+ objProto = typeof valueOf == 'function' && (objProto = valueOf.__proto__) && objProto.__proto__;
+
+ return objProto
+ ? value == objProto || (value.__proto__ == objProto && (skipArgsCheck || !isArguments(value)))
+ : isPlainFallback(value);
+ };
+
/**
* A shim implementation of `Object.keys` that produces an array of the given
* object's own enumerable property names.
@@ -1043,10 +1063,9 @@
* @param {Boolean} deep A flag to indicate a deep clone.
* @param {Object} [guard] Internally used to allow this method to work with
* others like `_.map` without using their callback `index` argument for `deep`.
- * @param {Array} [stack=[]] Internally used to keep track of traversed objects
- * to avoid circular references.
- * @param {Object} thorough Internally used to indicate whether or not to perform
- * a more thorough clone of non-object values.
+ * @param {Object} [data={}] Internally used to track traversed objects to avoid
+ * circular references and indicate whether to perform a more thorough clone
+ * of non-object values.
* @returns {Mixed} Returns the cloned `value`.
* @example
*
@@ -1067,23 +1086,25 @@
* shallow[0] === stooges[0];
* // => false
*/
- function clone(value, deep, guard, stack, thorough) {
+ function clone(value, deep, guard, data) {
if (value == null) {
return value;
}
if (guard) {
deep = false;
}
+ // init internal data
+ data || (data = { 'thorough': null });
+
// avoid slower checks on primitives
- thorough || (thorough = { 'value': null });
- if (thorough.value == null) {
+ if (data.thorough == null) {
// primitives passed from iframes use the primary document's native prototypes
- thorough.value = !!(BoolProto.clone || NumberProto.clone || StringProto.clone);
+ data.thorough = !!(BoolProto.clone || NumberProto.clone || StringProto.clone);
}
// use custom `clone` method if available
var isObj = objectTypes[typeof value];
- if ((isObj || thorough.value) && value.clone && isFunction(value.clone)) {
- thorough.value = null;
+ if ((isObj || data.thorough) && value.clone && isFunction(value.clone)) {
+ data.thorough = null;
return value.clone(deep);
}
// inspect [[Class]]
@@ -1120,31 +1141,33 @@
return ctor(value.source, reFlags.exec(value));
}
+ var clones = data.clones || (data.clones = []),
+ sources = data.sources || (data.sources = []),
+ length = clones.length;
+
// check for circular references and return corresponding clone
- stack || (stack = []);
- var length = stack.length;
while (length--) {
- if (stack[length].source == value) {
- return stack[length].value;
+ if (sources[length] == value) {
+ return clones[length];
}
}
// init cloned object
- length = value.length;
- var result = isArr ? ctor(length) : {};
+ var result = isArr ? ctor(length = value.length) : {};
// add current clone and original source value to the stack of traversed objects
- stack.push({ 'value': result, 'source': value });
+ clones.push(result);
+ sources.push(value);
// recursively populate clone (susceptible to call stack limits)
if (isArr) {
var index = -1;
while (++index < length) {
- result[index] = clone(value[index], deep, null, stack, thorough);
+ result[index] = clone(value[index], deep, null, data);
}
} else {
forOwn(value, function(objValue, key) {
- result[key] = clone(objValue, deep, null, stack, thorough);
+ result[key] = clone(objValue, deep, null, data);
});
}
return result;
@@ -1172,34 +1195,6 @@
'inLoop': 'if (result[index] == null) ' + extendIteratorOptions.inLoop
});
- /**
- * Creates a shallow clone of `object` excluding the specified properties.
- * Property names may be specified as individual arguments or as arrays of
- * property names. If `callback` is passed, it will be executed for each property
- * in the `object`, dropping the properties `callback` returns truthy for. The
- * `callback` is bound to `thisArg` and invoked with 3 arguments; (value, key, object).
- *
- * @static
- * @memberOf _
- * @alias omit
- * @category Objects
- * @param {Object} object The source object.
- * @param {Function|String} callback|[prop1, prop2, ...] The properties to drop
- * or the function called per iteration.
- * @param {Mixed} [thisArg] The `this` binding for the callback.
- * @returns {Object} Returns an object without the dropped properties.
- * @example
- *
- * _.drop({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
- * // => { 'name': 'moe', 'age': 40 }
- *
- * _.drop({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
- * return key.charAt(0) == '_';
- * });
- * // => { 'name': 'moe' }
- */
- var drop = createIterator(dropIteratorOptions);
-
/**
* Assigns enumerable properties of the source object(s) to the `destination`
* object. Subsequent sources will overwrite propery assignments of previous
@@ -1314,6 +1309,25 @@
return object ? hasOwnProperty.call(object, property) : false;
}
+ /**
+ * Creates an object composed of the inverted keys and values of the given `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to invert.
+ * @returns {Object} Returns the created inverted object.
+ * @example
+ *
+ * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
+ * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
+ */
+ var invert = createIterator({
+ 'args': 'object',
+ 'init': '{}',
+ 'inLoop': 'result[value] = index'
+ });
+
/**
* Checks if `value` is a boolean (`true` or `false`) value.
*
@@ -1412,10 +1426,9 @@
* @category Objects
* @param {Mixed} a The value to compare.
* @param {Mixed} b The other value to compare.
- * @param {Array} [stack=[]] Internally used to keep track of traversed objects
- * to avoid circular references.
- * @param {Object} thorough Internally used to indicate whether or not to perform
- * a more thorough comparison of non-object values.
+ * @param {Object} [data={}] Internally used track traversed objects to avoid
+ * circular references and indicate whether to perform a more thorough comparison
+ * of non-object values.
* @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
* @example
*
@@ -1428,32 +1441,31 @@
* _.isEqual(moe, clone);
* // => true
*/
- function isEqual(a, b, stack, thorough) {
+ function isEqual(a, b, data) {
// a strict comparison is necessary because `null == undefined`
if (a == null || b == null) {
return a === b;
}
+ // init internal data
+ data || (data = { 'thorough': null });
+
// avoid slower checks on non-objects
- thorough || (thorough = { 'value': null });
- if (thorough.value == null) {
+ if (data.thorough == null) {
// primitives passed from iframes use the primary document's native prototypes
- thorough.value = !!(BoolProto.isEqual || NumberProto.isEqual || StringProto.isEqual);
+ data.thorough = !!(BoolProto.isEqual || NumberProto.isEqual || StringProto.isEqual);
}
- if (objectTypes[typeof a] || objectTypes[typeof b] || thorough.value) {
+ if (objectTypes[typeof a] || objectTypes[typeof b] || data.thorough) {
// unwrap any LoDash wrapped values
- if (a._chain) {
- a = a._wrapped;
- }
- if (b._chain) {
- b = b._wrapped;
- }
+ a = a.__wrapped__ || a;
+ b = b.__wrapped__ || b;
+
// use custom `isEqual` method if available
if (a.isEqual && isFunction(a.isEqual)) {
- thorough.value = null;
+ data.thorough = null;
return a.isEqual(b);
}
if (b.isEqual && isFunction(b.isEqual)) {
- thorough.value = null;
+ data.thorough = null;
return b.isEqual(a);
}
}
@@ -1502,11 +1514,13 @@
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
- stack || (stack = []);
- var length = stack.length;
+ var stackA = data.stackA || (data.stackA = []),
+ stackB = data.stackB || (data.stackB = []),
+ length = stackA.length;
+
while (length--) {
- if (stack[length] == a) {
- return true;
+ if (stackA[length] == a) {
+ return stackB[length] == b;
}
}
@@ -1514,8 +1528,9 @@
result = true,
size = 0;
- // add `a` to the stack of traversed objects
- stack.push(a);
+ // add `a` and `b` to the stack of traversed objects
+ stackA.push(a);
+ stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
@@ -1526,7 +1541,7 @@
if (result) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
- if (!(result = isEqual(a[size], b[size], stack, thorough))) {
+ if (!(result = isEqual(a[size], b[size], data))) {
break;
}
}
@@ -1550,7 +1565,7 @@
// count the number of properties.
size++;
// deep compare each property value.
- if (!(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stack, thorough))) {
+ if (!(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], data))) {
return false;
}
}
@@ -1570,7 +1585,7 @@
while (++index < 7) {
prop = shadowed[index];
if (hasOwnProperty.call(a, prop) &&
- !(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stack, thorough))) {
+ !(hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], data))) {
return false;
}
}
@@ -1789,8 +1804,8 @@
* @param {Object} [source1, source2, ...] The source objects.
* @param {Object} [indicator] Internally used to indicate that the `stack`
* argument is an array of traversed objects instead of another source object.
- * @param {Array} [stack=[]] Internally used to keep track of traversed objects
- * to avoid circular references.
+ * @param {Object} [data={}] Internally used to track traversed objects to avoid
+ * circular references.
* @returns {Object} Returns the destination object.
* @example
*
@@ -1808,32 +1823,80 @@
* // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
*/
var merge = createIterator(extendIteratorOptions, {
- 'args': 'object, source, indicator, stack',
+ 'args': 'object, source, indicator',
'top':
- 'var destValue, found, isArr, stackLength, recursive = indicator == isPlainObject;\n' +
- 'if (!recursive) stack = [];\n' +
+ 'var isArr, recursive = indicator == isPlainObject,\n' +
+ ' data = recursive ? arguments[3] : { values: [], sources: [] };\n' +
'for (var argsIndex = 1, argsLength = recursive ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
' if (iteratee = arguments[argsIndex]) {',
'inLoop':
- 'if (value && ((isArr = isArray(value)) || isPlainObject(value))) {\n' +
- ' found = false; stackLength = stack.length;\n' +
+ 'if ((source = value) && ((isArr = isArray(source)) || isPlainObject(source))) {\n' +
+ ' var found = false, values = data.values, sources = data.sources, stackLength = sources.length;\n' +
' while (stackLength--) {\n' +
- ' if (found = stack[stackLength].source == value) break\n' +
+ ' if (found = sources[stackLength] == source) break\n' +
' }\n' +
' if (found) {\n' +
- ' result[index] = stack[stackLength].value\n' +
+ ' result[index] = values[stackLength]\n' +
' } else {\n' +
- ' destValue = (destValue = result[index]) && isArr\n' +
- ' ? (isArray(destValue) ? destValue : [])\n' +
- ' : (isPlainObject(destValue) ? destValue : {});\n' +
- ' stack.push({ value: destValue, source: value });\n' +
- ' result[index] = callee(destValue, value, isPlainObject, stack)\n' +
+ ' values.push(value = (value = result[index]) && isArr\n' +
+ ' ? (isArray(value) ? value : [])\n' +
+ ' : (isPlainObject(value) ? value : {})\n' +
+ ' );\n' +
+ ' sources.push(source);\n' +
+ ' result[index] = callee(value, source, isPlainObject, data)\n' +
' }\n' +
- '} else if (value != null) {\n' +
- ' result[index] = value\n' +
+ '} else if (source != null) {\n' +
+ ' result[index] = source\n' +
'}'
});
+ /**
+ * Creates a shallow clone of `object` excluding the specified properties.
+ * Property names may be specified as individual arguments or as arrays of
+ * property names. If `callback` is passed, it will be executed for each property
+ * in the `object`, omitting the properties `callback` returns truthy for. The
+ * `callback` is bound to `thisArg` and invoked with 3 arguments; (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The source object.
+ * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+ * or the function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Object} Returns an object without the omitted properties.
+ * @example
+ *
+ * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
+ * // => { 'name': 'moe', 'age': 40 }
+ *
+ * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
+ * return key.charAt(0) == '_';
+ * });
+ * // => { 'name': 'moe' }
+ */
+ var omit = createIterator(omitIteratorOptions);
+
+ /**
+ * Creates a two dimensional array of the given object's key-value pairs,
+ * i.e. `[[key1, value1], [key2, value2]]`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns new array of key-value pairs.
+ * @example
+ *
+ * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
+ * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
+ */
+ var pairs = createIterator({
+ 'args': 'object',
+ 'init':'[]',
+ 'inLoop': 'result' + (isKeysFast ? '[ownIndex] = ' : '.push') + '([index, value])'
+ });
+
/**
* Creates a shallow clone of `object` composed of the specified properties.
* Property names may be specified as individual arguments or as arrays of
@@ -1859,7 +1922,7 @@
* });
* // => { 'name': 'moe' }
*/
- var pick = createIterator(dropIteratorOptions, {
+ var pick = createIterator(omitIteratorOptions, {
'top':
'if (typeof callback != \'function\') {\n' +
' var prop,\n' +
@@ -1876,45 +1939,6 @@
'bottom': '}'
});
- /**
- * Gets the size of `value` by returning `value.length` if `value` is an
- * array, string, or `arguments` object. If `value` is an object, size is
- * determined by returning the number of own enumerable properties it has.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Array|Object|String} value The value to inspect.
- * @returns {Number} Returns `value.length` or number of own enumerable properties.
- * @example
- *
- * _.size([1, 2]);
- * // => 2
- *
- * _.size({ 'one': 1, 'two': 2, 'three': 3 });
- * // => 3
- *
- * _.size('curly');
- * // => 5
- */
- function size(value) {
- if (!value) {
- return 0;
- }
- var className = toString.call(value),
- length = value.length;
-
- // return `value.length` for `arguments` objects, arrays, strings, and DOM
- // query collections of libraries like jQuery and MooTools
- // http://code.google.com/p/fbug/source/browse/branches/firebug1.9/content/firebug/chrome/reps.js?r=12614#653
- // http://trac.webkit.org/browser/trunk/Source/WebCore/inspector/InjectedScriptSource.js?rev=125186#L609
- if (arrayLikeClasses[className] || (noArgsClass && isArguments(value)) ||
- (className == objectClass && length > -1 && length === length >>> 0 && isFunction(value.splice))) {
- return length;
- }
- return keys(value).length;
- }
-
/**
* Creates an array composed of the own enumerable property values of `object`.
*
@@ -2321,6 +2345,34 @@
'inLoop': '!' + filterIteratorOptions.inLoop
});
+ /**
+ * Gets the size of the `collection` by returning `collection.length` for arrays
+ * and array-like objects or the number of own enumerable properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to inspect.
+ * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+ * @example
+ *
+ * _.size([1, 2]);
+ * // => 2
+ *
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => 3
+ *
+ * _.size('curly');
+ * // => 5
+ */
+ function size(collection) {
+ if (!collection) {
+ return 0;
+ }
+ var length = collection.length;
+ return length > -1 && length === length >>> 0 ? length : keys(collection).length;
+ }
+
/**
* Checks if the `callback` returns a truthy value for **any** element of a
* `collection`. The function returns as soon as it finds passing value, and
@@ -2620,7 +2672,7 @@
if (fromIndex) {
if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? Math.max(0, length + fromIndex) : fromIndex) - 1;
+ index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) - 1;
} else {
index = sortedIndex(array, value);
return array[index] === value ? index : -1;
@@ -2748,7 +2800,7 @@
}
var index = array.length;
if (fromIndex && typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? Math.max(0, index + fromIndex) : Math.min(fromIndex, index - 1)) + 1;
+ index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
@@ -2864,6 +2916,41 @@
return result;
}
+ /**
+ * Creates an object composed from arrays of `keys` and `values`. Pass either
+ * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+ * two arrays, one of `keys` and one of corresponding `values`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} keys The array of keys.
+ * @param {Array} [values=[]] The array of values.
+ * @returns {Object} Returns an object composed of the given keys and
+ * corresponding values.
+ * @example
+ *
+ * _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
+ * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
+ */
+ function object(keys, values) {
+ if (!keys) {
+ return {};
+ }
+ var index = -1,
+ length = keys.length,
+ result = {};
+
+ while (++index < length) {
+ if (values) {
+ result[keys[index]] = values[index];
+ } else {
+ result[keys[index][0]] = keys[index][1];
+ }
+ }
+ return result;
+ }
+
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to but not including `stop`. This method is a port of Python's
@@ -2904,7 +2991,7 @@
// use `Array(length)` so V8 will avoid the slower "dictionary" mode
// http://www.youtube.com/watch?v=XAqIpGU8ZZk#t=16m27s
var index = -1,
- length = Math.max(0, Math.ceil((end - start) / step)),
+ length = nativeMax(0, Math.ceil((end - start) / step)),
result = Array(length);
while (++index < length) {
@@ -2920,7 +3007,7 @@
*
* @static
* @memberOf _
- * @alias tail
+ * @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Number} [n] The number of elements to return.
@@ -2963,7 +3050,7 @@
result = Array(length);
while (++index < length) {
- rand = Math.floor(Math.random() * (index + 1));
+ rand = nativeFloor(nativeRandom() * (index + 1));
result[index] = result[rand];
result[rand] = array[index];
}
@@ -3186,36 +3273,6 @@
return result;
}
- /**
- * Creates an object composed from an array of `keys` and an array of `values`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} keys The array of keys.
- * @param {Array} [values=[]] The array of values.
- * @returns {Object} Returns an object composed of the given keys and
- * corresponding values.
- * @example
- *
- * _.zipObject(['moe', 'larry', 'curly'], [30, 40, 50]);
- * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
- */
- function zipObject(keys, values) {
- if (!keys) {
- return {};
- }
- var index = -1,
- length = keys.length,
- result = {};
-
- values || (values = []);
- while (++index < length) {
- result[keys[index]] = values[index];
- }
- return result;
- }
-
/*--------------------------------------------------------------------------*/
/**
@@ -3441,7 +3498,7 @@
function delayed() {
timeoutId = null;
if (!immediate) {
- func.apply(thisArg, args);
+ result = func.apply(thisArg, args);
}
}
@@ -3627,7 +3684,7 @@
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
- func.apply(thisArg, args);
+ result = func.apply(thisArg, args);
}
return function() {
@@ -3745,14 +3802,14 @@
var func = lodash[methodName] = object[methodName];
LoDash.prototype[methodName] = function() {
- var args = [this._wrapped];
+ var args = [this.__wrapped__];
if (arguments.length) {
push.apply(args, arguments);
}
var result = func.apply(lodash, args);
- if (this._chain) {
+ if (this.__chain__) {
result = new LoDash(result);
- result._chain = true;
+ result.__chain__ = true;
}
return result;
};
@@ -3776,6 +3833,40 @@
return this;
}
+ /**
+ * Produces a random number between `min` and `max` (inclusive). If only one
+ * argument is passed, a number between `0` and the given number will be returned.
+ * If no arguments are passed `_.random` will act as `Math.random`.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Number} min The minimum possible value.
+ * @param {Number} max The maximum possible value.
+ * @returns {Number} Returns a random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => a number between 1 and 5
+ *
+ * _.random(5);
+ * // => also a number between 1 and 5
+ *
+ * _.random();
+ * // => an integer between 0 and less than 1
+ */
+ function random(min, max) {
+ if (min == null && max == null) {
+ return nativeRandom();
+ }
+ min = +min || 0;
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + nativeFloor(nativeRandom() * ((+max || 0) - min + 1));
+ }
+
/**
* Resolves the value of `property` on `object`. If `property` is a function
* it will be invoked and its result returned, else the property value is
@@ -3984,10 +4075,8 @@
try {
result = Function('_', 'return ' + text)(lodash);
} catch(e) {
- // defer syntax errors until the compiled template is executed to allow
- // examining the `source` property beforehand and for consistency,
- // because other template related errors occur at execution
- result = function() { throw e; };
+ e.source = text;
+ throw e;
}
if (data) {
@@ -4012,11 +4101,11 @@
* @param {Mixed} [thisArg] The `this` binding for the callback.
* @example
*
- * _.times(3, function() { genie.grantWish(); });
- * // => calls `genie.grantWish()` 3 times
+ * _.times(3, function(n) { genie.grantWish(n); });
+ * // => calls `genie.grantWish(n)` three times, passing `n` of `0`, `1`, and `2` respectively
*
- * _.times(3, function() { this.grantWish(); }, genie);
- * // => also calls `genie.grantWish()` 3 times
+ * _.times(3, function(n) { this.grantWish(n); }, genie);
+ * // => also calls `genie.grantWish(n)` three times
*/
function times(n, callback, thisArg) {
var index = -1;
@@ -4095,7 +4184,7 @@
*/
function chain(value) {
value = new LoDash(value);
- value._chain = true;
+ value.__chain__ = true;
return value;
}
@@ -4139,7 +4228,7 @@
* // => [1, 2, 3]
*/
function wrapperChain() {
- this._chain = true;
+ this.__chain__ = true;
return this;
}
@@ -4156,7 +4245,7 @@
* // => [1, 2, 3]
*/
function wrapperValue() {
- return this._wrapped;
+ return this.__wrapped__;
}
/*--------------------------------------------------------------------------*/
@@ -4168,7 +4257,7 @@
* @memberOf _
* @type String
*/
- lodash.VERSION = '0.6.1';
+ lodash.VERSION = '0.7.0';
// assign static methods
lodash.after = after;
@@ -4185,7 +4274,6 @@
lodash.defer = defer;
lodash.delay = delay;
lodash.difference = difference;
- lodash.drop = drop;
lodash.escape = escape;
lodash.every = every;
lodash.extend = extend;
@@ -4203,6 +4291,7 @@
lodash.indexOf = indexOf;
lodash.initial = initial;
lodash.intersection = intersection;
+ lodash.invert = invert;
lodash.invoke = invoke;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
@@ -4230,10 +4319,14 @@
lodash.min = min;
lodash.mixin = mixin;
lodash.noConflict = noConflict;
+ lodash.object = object;
+ lodash.omit = omit;
lodash.once = once;
+ lodash.pairs = pairs;
lodash.partial = partial;
lodash.pick = pick;
lodash.pluck = pluck;
+ lodash.random = random;
lodash.range = range;
lodash.reduce = reduce;
lodash.reduceRight = reduceRight;
@@ -4259,13 +4352,13 @@
lodash.without = without;
lodash.wrap = wrap;
lodash.zip = zip;
- lodash.zipObject = zipObject;
// assign aliases
lodash.all = every;
lodash.any = some;
lodash.collect = map;
lodash.detect = find;
+ lodash.drop = rest;
lodash.each = forEach;
lodash.foldl = reduce;
lodash.foldr = reduceRight;
@@ -4273,7 +4366,6 @@
lodash.include = contains;
lodash.inject = reduce;
lodash.methods = functions;
- lodash.omit = drop;
lodash.select = filter;
lodash.tail = rest;
lodash.take = first;
@@ -4301,7 +4393,7 @@
var func = ArrayProto[methodName];
LoDash.prototype[methodName] = function() {
- var value = this._wrapped;
+ var value = this.__wrapped__;
func.apply(value, arguments);
// avoid array-like object bugs with `Array#shift` and `Array#splice` in
@@ -4309,9 +4401,9 @@
if (hasObjectSpliceBug && value.length === 0) {
delete value[0];
}
- if (this._chain) {
+ if (this.__chain__) {
value = new LoDash(value);
- value._chain = true;
+ value.__chain__ = true;
}
return value;
};
@@ -4322,12 +4414,12 @@
var func = ArrayProto[methodName];
LoDash.prototype[methodName] = function() {
- var value = this._wrapped,
+ var value = this.__wrapped__,
result = func.apply(value, arguments);
- if (this._chain) {
+ if (this.__chain__) {
result = new LoDash(result);
- result._chain = true;
+ result.__chain__ = true;
}
return result;
};
diff --git a/lodash.min.js b/lodash.min.js
index 423fe5a963..ead0d5489e 100644
--- a/lodash.min.js
+++ b/lodash.min.js
@@ -1,41 +1,42 @@
/*!
- Lo-Dash 0.6.1 lodash.com/license
+ Lo-Dash 0.7.0 lodash.com/license
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
*/
-;(function(e,t){function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||V),s=i?{}:e;if(i)for(var o=t-1;++o-1&&l===l>>>0){"),u.o&&(t+="if(z.call(j)==x){j=j.split('')}"),t+=u.c.d+";while(++in;n++)t+="i='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(f&&f.prototype===j)&&"),t+="g.call(j,i)){A=j[i];"+u.m.i+"}"}if(u.c||u.n)t+="}"}return t+=u.e+";return u",Function("D,E,F,I,e,K,g,h,N,P,R,T,U,k,X,Y,m,r,w,x,z","var G=function("+e+"){"+t+"};return G")(qt,q,_,f,at,un,ft,D,k,b,tn,w,E,p,xt,Wt,gt,ct,ht,Nt,pt)}function f(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;return e===t?1:n===t?-1:en?1:r";var n=ut.length;return ut[n]="'+__e("+t+")+'",ot+n}function m(e,t,n,i){return i?(e=ut.length,ut[e]="';"+i+";__p+='",ot+e):t?v(r,t):g(r,n)}function g(e,t){if(e&&J.test(t))return"";var n=ut.length;return ut[n]="'+((__t=("+t+"))==null?'':__t)+'",ot+n}function y(e){return zt[e]}function b(e){return pt.call(e)==yt}function w
-(e){return"function"==typeof e}function E(e,t){return e?e==U||e.__proto__==U&&(t||!b(e)):i}function S(e,t,s,o,u){if(e==r)return e;s&&(t=i),u||(u={d:r}),u.d==r&&(u.d=!(!R.clone&&!z.clone&&!W.clone));if(((s=Wt[typeof e])||u.d)&&e.clone&&w(e.clone))return u.d=r,e.clone(t);if(s){var a=pt.call(e);if(!Rt[a]||_t&&b(e))return e;var f=a==bt,s=f||(a==xt?E(e,n):s)}if(!s||!t)return s?f?ht.call(e):on({},e):e;s=e.constructor;switch(a){case wt:return new s(e==n);case Et:return new s(+e);case St:case Nt:return new
-s(e);case Tt:return s(e.source,Z.exec(e))}o||(o=[]);for(a=o.length;a--;)if(o[a].c==e)return o[a].d;var a=e.length,l=f?s(a):{};o.push({d:l,c:e});if(f)for(f=-1;++f++u;)if(c=st[u],ft.call(e,c)&&(!ft.call(t,c)||!x(e[c],t[c],s,o)))return i;return n}function T(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=p(t,r));if(-1>>0){var o=Pt&&pt.call(e)==Nt?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=cn(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function N(e,t,n){if(e)return t==r||n?e[0]:ht.call(e,0,t)}function C(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length;++in?Math.max(0,i+n):n)-1}for(
-;++ri&&(i=e[s]);return i}for(n&&(t=p(t,n));++sr&&(r=n,i=e[s]);return i}function A(e,t,n){return e?ht.call(e,t==r||n?1:t):[]}function O(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=_(n,r));for(t=n(t);i>>1,n(e[r])>>1,e[r]k(a,r))a.push(r),s.push(e[o]);return s}function _(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?s.concat(ht.call(o)):s),this instanceof n?(d.prototype=e.prototype,u=new d,(o=e.apply(u,o))&&Wt[typeof o]?o:u):e.apply(u,o)}var r,i=w(e);if(i){if(jt||dt&&2|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/
-,K=/&(?:amp|lt|gt|quot|#x27);/g,Q=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,Y=/(__e\(.*?\)|\b__t\))\+'';/g,Z=/\w*$/,et=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,tt=RegExp("^"+(U.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),nt=/__token__(\d+)/g,rt=/[&<>"']/g,it=/['\n\r\t\u2028\u2029\\]/g,st="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="__token__",ut=[],at=q.concat,ft=U.hasOwnProperty,lt=q.push
-,ct=U.propertyIsEnumerable,ht=q.slice,pt=U.toString,dt=tt.test(dt=ht.bind)&&dt,vt=tt.test(vt=Array.isArray)&&vt,mt=e.isFinite,gt=tt.test(gt=Object.keys)&>,yt="[object Arguments]",bt="[object Array]",wt="[object Boolean]",Et="[object Date]",St="[object Number]",xt="[object Object]",Tt="[object RegExp]",Nt="[object String]",Ct=e.clearTimeout,kt=e.setTimeout,Lt,At,Ot,Mt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments
-)Mt=!r;Lt=4>(n+"").length,Ot="x"!=n[0],At=(n.splice.call(t,0,1),t[0])})(1);var _t=!b(arguments),Dt="x"!=ht.call("x")[0],Pt="xx"!="x"[0]+Object("x")[0];try{var Ht=("[object Object]",pt.call(e.document||0)==xt)}catch(Bt){}var jt=dt&&/\n|Opera/.test(dt+pt.call(e.opera)),Ft=gt&&/^.+$|true/.test(gt+!!e.attachEvent),It=!jt,qt={"[object Arguments]":n,"[object Array]":n,"[object Boolean]":i,"[object Date]":i,"[object Function]":i,"[object Number]":i,"[object Object]":i,"[object RegExp]":i,"[object String]"
-:n},Rt={"[object Arguments]":i,"[object Array]":n,"[object Boolean]":n,"[object Date]":n,"[object Function]":i,"[object Number]":n,"[object Object]":n,"[object RegExp]":n,"[object String]":n},Ut={"&":"&","<":"<",">":">",'"':""","'":"'"},zt={"&":"&","<":"<",">":">",""":'"',"'":"'"},Wt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Xt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings=
-{escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var Vt={a:"d,c,y",j:"d",q:"if(!c)c=h;else if(y)c=k(c,y)",i:"if(c(A,i,d)===false)return u"},$t={j:"{}",q:"var q;if(typeof c!='function'){var ii=c;c=function(A){return A[ii]}}else if(y)c=k(c,y)",i:"q=c(A,i,d);(g.call(u,q)?u[q]++:u[q]=1)"},Jt={r:i,a:"n,c,y",j:"{}",q:"var S=typeof c=='function';if(!S){var t=e.apply(E,arguments)}else if(y)c=k(c,y)",i:"if(S?!c(A,i,n):N(t,i)<0)u[i]=A"},Kt={j:"true",i:"if(!c(A,i,d))return!u"
-},Qt={r:i,s:i,a:"n",j:"n",q:"for(var a=1,b=arguments.length;a-1&&l===l>>>0&&T(A.splice)))return!l",i:{l:"return false"}}),cn=gt?function(e){var t=typeof e;return"function"==t&&ct.call(e,"prototype")?nn(e):e&&Wt[t]?gt(e):[]}:nn,hn=a(Qt,{a:"n,ee,O,ff",q:"var J,L,Q,gg,dd=O==U;if(!dd)ff=[];for(var a=1,b=dd?2:arguments.length;a-1"},i:"if(A===hh)return true"}),mn=a(Vt,$t),gn=a(Vt,Kt),yn=a(Vt,Gt),bn=a(Vt,Yt,{j:"",i:"if(c(A,i,d))return A"}),wn=a(Vt,Yt),En=a(Vt,$t,{i:"q=c(A,i,d);(g.call(u,q)?u[q]:u[q]=[]).push(A)"}),Sn=a(en,{a:"d,V",q:"var C=w.call(arguments,2),S=typeof V=='function'"
-,i:{b:"u[i]=(S?V:A[V]).apply(A,C)",l:"u"+(Ft?"[o]=":".push")+"((S?V:A[V]).apply(A,C))"}}),xn=a(Vt,en),Tn=a(en,{a:"d,bb",i:{b:"u[i]=A[bb]",l:"u"+(Ft?"[o]=":".push")+"(A[bb])"}}),Nn=a({a:"d,c,B,y",j:"B",q:"var W=arguments.length<3;if(y)c=k(c,y)",d:{b:"if(W)u=j[++i]"},i:{b:"u=c(u,A,i,d)",l:"u=W?(W=false,A):c(u,A,i,d)"}}),Cn=a(Vt,Gt,{i:"!"+Gt.i}),kn=a(Vt,Kt,{j:"false",i:Kt.i.replace("!","")}),Ln=a(Vt,$t,en,{i:{b:"u[i]={a:c(A,i,d),b:i,d:A}",l:"u"+(Ft?"[o]=":".push")+"({a:c(A,i,d),b:i,d:A})"},e:"u.sort(I);l=u.length;while(l--)u[l]=u[l].d"
-}),An=a(Gt,{a:"d,aa",q:"var t=[];K(aa,function(A,q){t.push(q)});var cc=t.length",i:"for(var q,Z=true,s=0;s1){for(var i=1;ie?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=_,s.bindAll=On,s.chain=function(e){return e=new o(e),e._chain=n,e},s.clone=
-S,s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++nk(t,n)){for(var a=1;an?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(e[r]===t)return r;return-1
-},s.map=xn,s.max=L,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return ft.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=hn,s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s>>0&&w(e.splice)?n:cn(e).length},s.some=kn,s.sortBy=Ln,s.sortedIndex=O,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var e=e+"",o,u;o=n.escape;var a=n.evaluate,f=n.interpolate,h=s.templateSettings,p=n=n.variable||h.variable
-;o==r&&(o=h.escape),a==r&&(a=h.evaluate||i),f==r&&(f=h.interpolate),o&&(e=e.replace(o,v)),f&&(e=e.replace(f,g)),a!=H&&(H=a,F=RegExp("|"+(a?"|"+a.source:""),"g")),o=ut.length,e=e.replace(F,m),o=o!=ut.length,e="__p += '"+e.replace(it,c).replace(nt,l)+"';",ut.length=0,p||(n=B||"obj",o?e="with("+n+"){"+e+"}":(n!=B&&(B=n,j=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(et,"$&"+n+".").replace(j,"$1__d"))),e=(o?e.replace(Q,""):e).replace(G,"$1").replace(Y,"$1;")
-,e="function("+n+"){"+(p?"":n+"||("+n+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(p?"":",__d="+n+"."+n+"||"+n)+";")+e+"return __p}";try{u=Function("_","return "+e)(s)}catch(d){u=function(){throw d}}return t?u(t):(u.source=e,u)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e.apply(o,i)):u||(u=kt(n,f)),s}},s.times=
-function(e,t,n){var r=-1;if(n)for(;++r>>0?(Dt?pt.call(e)==Nt:"string"==typeof e)?e.split(""):ht.call(e):dn(e)},s.unescape=function(e){return e==r?"":(e+"").replace(K,y)},s.union=function(){for(var e=-1,t=[],n=at.apply(t,arguments),r=n.length;++ek(t,n[e])&&t.push(n[e]);return t},s.uniq=M,s.uniqueId=function(e){var t=X++;return e?e+t:t},s.values=
-dn,s.where=An,s.without=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=u(arguments,1,20);++n=(n||V),s=i?{}:e;if(i)for(var o=t-1;++o-1&&l===l>>>0){"),u.o&&(t+="if(z.call(j)==x){j=j.split('')}"),t+=u.c.d+";while(++in;n++)t+="i='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(f&&f.prototype===j)&&"),t+="g.call(j,i)){A=j[i];"+u.m.i+"}"}if(u.c||u.n)t+="}"}return t+=u.e+";return u",Function("D,E,F,I,e,K,g,h,N,P,R,T,U,k,X,Y,m,r,w,x,z","var G=function("+e+"){"+t+"};return G")(Xt,q,_,f,ft,hn,lt,D,k,b,un,w,an,p,Lt,Kt,bt,ht,pt,Ot,dt)}function f(e,n){var r=e.c,i=n.c,e=e.b,n=n.b;if(e!==n){if(e>n||e===t)return 1;if(e";var n=at.length;return at[n]="'+__e("+t+")+'",ot+n+ut}function m(e,t,n,i){return i?(e=at.length,at[e]="';"+i+";__p+='",ot+e+ut):t?v(r,t):g(r,n)}function g(e,t){if(e&&J.test(t))return"";var n=at.length;return at[n]="'+((__t=("+t+"))==null?'':__t)+'",ot+n+ut}function y(e){return Jt[e]}function b(e){return dt
+.call(e)==xt}function w(e){return"function"==typeof e}function E(e,t){var n=i;if(!e||"object"!=typeof e||!t&&b(e))return n;var r=e.constructor;return(!qt||"function"==typeof e.toString||"string"!=typeof (e+""))&&(!w(r)||r instanceof r)?Ht?(hn(e,function(e,t,r){return n=!lt.call(r,t),i}),n===i):(hn(e,function(e,t){n=t}),n===i||lt.call(e,n)):n}function S(e,t,s,o){if(e==r)return e;s&&(t=i),o||(o={e:r}),o.t==r&&(o.t=!(!R.clone&&!z.clone&&!W.clone));if(((s=Kt[typeof e])||o.t)&&e.clone&&w(e.clone))return o
+.t=r,e.clone(t);if(s){var u=dt.call(e);if(!Vt[u]||jt&&b(e))return e;var a=u==Tt,s=a||(u==Lt?an(e,n):s)}if(!s||!t)return s?a?pt.call(e):cn({},e):e;s=e.constructor;switch(u){case Nt:return new s(e==n);case Ct:return new s(+e);case kt:case Ot:return new s(e);case At:return s(e.source,Z.exec(e))}for(var f=o.a||(o.a=[]),l=o.d||(o.d=[]),u=f.length;u--;)if(l[u]==e)return f[u];var c=a?s(u=e.length):{};f.push(c),l.push(e);if(a)for(a=-1;++a++o;)if(h=st[o],lt.call(e,h)&&(!lt.call(t,h)||!x(e[h],t[h],s)))return i;return n}function T(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=p(t,r));if(-1>>0){var o=It&&dt.call(e)==Ot?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=gn(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function N(e,t,n){if(e)return t==r||n?e[0]
+:pt.call(e,0,t)}function C(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length;++in?wt(0,i+n):n)-1}for(;++ri&&(i=e[s]);return i}for(n&&(t=p(t,n));++sr&&(r=n,i=e[s]);return i}
+function A(e,t,n){return e?pt.call(e,t==r||n?1:t):[]}function O(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=_(n,r));for(t=n(t);i>>1,n(e[r])>>1,e[r]k(a,r))a.push(r),s.push(e[o]);return s}function _(e,t){function n(){var o=arguments,u=t;return i||
+(e=t[r]),s.length&&(o=o.length?s.concat(pt.call(o)):s),this instanceof n?(d.prototype=e.prototype,u=new d,(o=e.apply(u,o))&&Kt[typeof o]?o:u):e.apply(u,o)}var r,i=w(e);if(i){if(Ut||vt&&2|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,K=/&(?:amp|lt|gt|quot|#x27);/g,Q=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,Y=/(__e\(.*?\)|\b__t\))\+'';/g,Z=/\w*$/,et=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,tt=
+RegExp("^"+(U.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),nt=/__token(\d+)__/g,rt=/[&<>"']/g,it=/['\n\r\t\u2028\u2029\\]/g,st="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="__token",ut="__",at=[],ft=q.concat,lt=U.hasOwnProperty,ct=q.push,ht=U.propertyIsEnumerable,pt=q.slice,dt=U.toString,vt=tt.test(vt=pt.bind)&&vt,mt=Math.floor,gt=tt.test(gt=Array.isArray)&>,yt=e.isFinite,bt=tt.test
+(bt=Object.keys)&&bt,wt=Math.max,Et=Math.min,St=Math.random,xt="[object Arguments]",Tt="[object Array]",Nt="[object Boolean]",Ct="[object Date]",kt="[object Number]",Lt="[object Object]",At="[object RegExp]",Ot="[object String]",Mt=e.clearTimeout,_t=e.setTimeout,Dt,Pt,Ht,Bt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Bt=!r;Dt=4>(n+"").length,Ht="x"!=n[0],Pt=(n.splice.call(t,0,1),t[0])})(1);var jt=!b(arguments
+),Ft="x"!=pt.call("x")[0],It="xx"!="x"[0]+Object("x")[0];try{var qt=("[object Object]",dt.call(e.document||0)==Lt)}catch(Rt){}var Ut=vt&&/\n|Opera/.test(vt+dt.call(e.opera)),zt=bt&&/^.+$|true/.test(bt+!!e.attachEvent),Wt=!Ut,Xt={};Xt[Nt]=Xt[Ct]=Xt["[object Function]"]=Xt[kt]=Xt[Lt]=Xt[At]=i,Xt[xt]=Xt[Tt]=Xt[Ot]=n;var Vt={};Vt[xt]=Vt["[object Function]"]=i,Vt[Tt]=Vt[Nt]=Vt[Ct]=Vt[kt]=Vt[Lt]=Vt[At]=Vt[Ot]=n;var $t={"&":"&","<":"<",">":">",'"':""","'":"'"},Jt={"&":"&","<":"<"
+,">":">",""":'"',"'":"'"},Kt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Qt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var Gt={a:"d,c,y",j:"d",q:"if(!c)c=h;else if(y)c=k(c,y)",i:"if(c(A,i,d)===false)return u"},Yt={j:"{}",q:"var q;if(typeof c!='function'){var ii=c;c=function(A){return A[ii]}}else if(y)c=k(c,y)"
+,i:"q=c(A,i,d);(g.call(u,q)?u[q]++:u[q]=1)"},Zt={j:"true",i:"if(!c(A,i,d))return!u"},en={r:i,s:i,a:"n",j:"n",q:"for(var a=1,b=arguments.length;a-1&&l===l>>>0&&T(A.splice)))return!l",i:{l:"return false"}}),gn=bt?function(e){var t=typeof e;return"function"==t&&ht.call(e,"prototype")?fn(e):e&&Kt[t]?bt(e):[]}:fn,yn=a(en,{a:"n,ee,O",q:"var Q,dd=O==U,J=dd?arguments[3]:{g:[],d:[]};for(var a=1,b=dd?2:arguments.length;a-1"},i:"if(A===hh)return true"}),Tn=a(Gt,Yt),Nn=a(Gt,Zt),Cn=a(Gt,tn),kn=a(Gt,nn,{j:"",i:"if(c(A,i,d))return A"}),Ln=a(Gt,nn),An=a(Gt,Yt,{i:"q=c(A,i,d);(g.call(u,q)?u[q]:u[q]=[]).push(A)"
+}),On=a(sn,{a:"d,V",q:"var C=w.call(arguments,2),S=typeof V=='function'",i:{b:"u[i]=(S?V:A[V]).apply(A,C)",l:"u"+(zt?"[o]=":".push")+"((S?V:A[V]).apply(A,C))"}}),Mn=a(Gt,sn),_n=a(sn,{a:"d,bb",i:{b:"u[i]=A[bb]",l:"u"+(zt?"[o]=":".push")+"(A[bb])"}}),Dn=a({a:"d,c,B,y",j:"B",q:"var W=arguments.length<3;if(y)c=k(c,y)",d:{b:"if(W)u=j[++i]"},i:{b:"u=c(u,A,i,d)",l:"u=W?(W=false,A):c(u,A,i,d)"}}),Pn=a(Gt,tn,{i:"!"+tn.i}),Hn=a(Gt,Zt,{j:"false",i:Zt.i.replace("!","")}),Bn=a(Gt,Yt,sn,{i:{b:"u[i]={b:c(A,i,d),c:i,f:A}"
+,l:"u"+(zt?"[o]=":".push")+"({b:c(A,i,d),c:i,f:A})"},e:"u.sort(I);l=u.length;while(l--)u[l]=u[l].f"}),jn=a(tn,{a:"d,aa",q:"var t=[];K(aa,function(A,q){t.push(q)});var cc=t.length",i:"for(var q,Z=true,s=0;s1){for(var i=1;ie?t():function(){if(1>--e)return t.apply
+(this,arguments)}},s.bind=_,s.bindAll=Fn,s.chain=function(e){return e=new o(e),e.__chain__=n,e},s.clone=S,s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++nk(t,n)){for(var a=1;an?wt(0,r+n):Et(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.map=Mn,s.max=L,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return lt.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=yn,s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s>>0?t:gn(e).length},s.some=Hn,s.sortBy=Bn,s.sortedIndex=O,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var e=e+"",o,u;o=n.escape;var a=n.evaluate,f=n.interpolate,h=s.templateSettings,p=n=n.variable||h.variable;o==r&&(o=h.escape),a==r&&(a=h.evaluate||i),f==r&&(f=h.interpolate),o&&(e=e.replace(o,v)),f&&(e=e.replace(f,g)),a!=H&&(H=a,F=RegExp("|"+(a?"|"+a.source:""),"g")),o=at.length,e=e.replace(F,m),o=o!=at.length,e="__p += '"+e
+.replace(it,c).replace(nt,l)+"';",at.length=0,p||(n=B||"obj",o?e="with("+n+"){"+e+"}":(n!=B&&(B=n,j=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(et,"$&"+n+".").replace(j,"$1__d"))),e=(o?e.replace(Q,""):e).replace(G,"$1").replace(Y,"$1;"),e="function("+n+"){"+(p?"":n+"||("+n+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(p?"":",__d="+n+"."+n+"||"+n)+";")+e+"return __p}";try{u=Function("_","return "+e)(s)}catch(d){throw d
+.source=e,d}return t?u(t):(u.source=e,u)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e.apply(o,i)):u||(u=_t(n,f)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r>>0?(Ft?dt.call(e)==Ot:"string"==typeof e)?e.split(""):pt.call
+(e):Sn(e)},s.unescape=function(e){return e==r?"":(e+"").replace(K,y)},s.union=function(){for(var e=-1,t=[],n=ft.apply(t,arguments),r=n.length;++ek(t,n[e])&&t.push(n[e]);return t},s.uniq=M,s.uniqueId=function(e){var t=X++;return e?e+t:t},s.values=Sn,s.where=jn,s.without=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=u(arguments,1,20);++nTest
-
+
+
+
diff --git a/test/index.html b/test/index.html
index 102e0c700e..e41af99206 100644
--- a/test/index.html
+++ b/test/index.html
@@ -32,9 +32,6 @@
Object.keys = Object._keys;
delete Object._keys;
- // set to test `_.noConflict`
- _ = 1;
-
// load Lo-Dash again to overwrite the existing `_` value
document.write('
-
+
+