Harder, Better, Faster, Stronger: Lo-Dash v3
Lo-Dash is a utility library delivering consistency, customization, performance & extras. It is also one the most dependent upon NPM packages. After a complete overhaul (over 800 commits since it has been bumped to v3.0.0-pre), version 3 boosts increased performance and a whole lot of new features.
3.0.0 version release notes summarize the changes.
Lo-Dash 3.0.0 (lodash) has been released on 2015-01-26.
Version 3.0.0 (2015-01-26) is available from the NPM:
npm install lodashlodash is also available in a variety of other builds & module formats.
- npm packages for modern, compatibility, & per method builds
- AMD modules for modern & compatibility builds
- ES modules for the modern build
With version 3.0.0, "Lo-Dash" has been renamed to "lodash".
This post focuses on the new features. For breaking changes, refer to the changelog.
There is a lodash-migrate package that assists with migrating code from older lodash versions to the latest release.
We have improved performance 20-40% overall in v3 by better utilizing the JIT in JavaScript engines, using internal helper functions that avoid optimization disqualifications & increase the likelihood of function inlining.
We are using Set & WeakMap for performance gains. This gives all modern browsers a boost & also means lodash will have significantly faster array/function methods in io.js over Node.js because io.js has Set/WeakMap on by default.
- Improved overall performance 20-40%.
- Method chaining supports lazy evaluation.
- Methods with support for shortcut fusion:
- _.drop
- _.dropRight
- _.dropRightWhile
- _.dropWhile
- _.filter
- _.first
- _.initial
- _.last
- _.map
- _.pluck
- _.reject
- _.rest
- _.reverse
- _.slice
- _.take
- _.takeRight
- _.takeRightWhile
- _.takeWhile
- _.where
- Other optimized methods:
- _.bind
- _.clone
- _.cloneDeep
- _.compact
- _.compose
- _.contains
- _.difference
- _.escape
- _.flatten
- _.invoke
- _.isEqual
- _.isObject
- _.matches
- _.max
- _.min
- _.partial
- _.shuffle
- _.unescape
- _.uniq
- _.without
- _.zip
Refer to the official changelog.
There is a ES6 branch of Lo-Dash v3. It is using ES6 modules, Set & WeakMap, supports cloning typed arrays & aligns many methods to ES6.
Lo-Dash is tested and works with io.js.
In contrast to eager evaluation, lazy evaluation is an evaluation strategy which delays the evaluation of an expression until it is needed. Lo-Dash is using lazy evaluation to optimize the number of cycles needed to perform an operation. When result set sorting is not important and only a subset of the data is needed, this will result in a smaller memory footprint and smaller number of cycles.
You have a collection of 100,000 products. Each product is described using a price. You need to get 5 products whose price is less than 0.5. There are two functions that are used to derive the product price, derivePrice1 and derivePrice2.
Eager evaluation will derive price of each product before proceeding to filter the collection.
Lazy evaluation applies both functions to each member of the collection until filter and take conditions are satisfied.
Lazy evaluation uses pipeline to process the intermediate data. Performing operation in a pipeline gets away without creating an array to store the intermediate results. Accessing the array once reduces the overhead, esp. when the data source is large and accessing memory is expensive.
This does not affect Lo-Dash API. However, it is useful to know that your clunky array is handled in a resource efficient manner.
Lazy evaluation does not compute the chain until .value() is called (explicitly or implicitly). The benefit is that you can prepare a complex query and delay the execution until the time it is needed.
In some scenarios, lazy evaluation reduces the footprint of the application and the execution time. Filip Zawada introduced lazy evaluation to Lo-Dash. He has written a blog post about lazy evaluation in the context of Lo-Dash.
Lazy evaluation is not a new concept in JavaScript. lazy.js is another utility library that implements lazy evaluation. Nevertheless, lazy evaluation is a nice addition to Lo-Dash that does not affect the API.
47 new methods have been added. The official documentation has not been released. I have written a node script that pulls each module from the ES6 branch and parses the comments to generate documentation.
| Name | Description |
|---|---|
camelCase | Converts string to camel case. See Wikipedia for more details. |
capitalize | Capitalizes the first character of string. |
deburr | Used to match latin-1 supplementary letters (excluding mathematical operators). |
endsWith | Checks if string ends with the given target string. |
escapeRegExp | Used to match RegExp special characters. See this article on RegExp characters for more details. |
kebabCase | Converts string to kebab case (a.k.a. spinal case). See Wikipedia for more details. |
pad | Native method references. |
padLeft | Pads string on the left side if it is shorter then the given padding length. The chars string may be truncated if the number of padding characters exceeds the padding length. |
padRight | Pads string on the right side if it is shorter then the given padding length. The chars string may be truncated if the number of padding characters exceeds the padding length. |
repeat | Native method references. |
snakeCase | Converts string to snake case. See Wikipedia for more details. |
startsWith | Checks if string starts with the given target string. |
trim | Removes leading and trailing whitespace or specified characters from string. |
trimLeft | Removes leading whitespace or specified characters from string. |
trimRight | Removes trailing whitespace or specified characters from string. |
trunc | Used as default options for _.trunc. |
words | Used to match words to create compound words. |
| Name | Description |
|---|---|
chunk | Native method references. |
dropRight | Creates a slice of array with n elements dropped from the end. |
dropRightWhile | Creates a slice of array excluding elements dropped from the end. Elements are dropped until predicate returns falsey. The predicate is bound to thisArg and invoked with three arguments; (value, index, array). |
dropWhile | Creates a slice of array excluding elements dropped from the beginning. Elements are dropped until predicate returns falsey. The predicate is bound to thisArg and invoked with three arguments; (value, index, array). |
flattenDeep | Recursively flattens a nested array. |
pullAt | Removes elements from array corresponding to the given indexes and returns an array of the removed elements. Indexes may be specified as an array of indexes or as individual arguments. Note: Unlike _.at, this method mutates array. |
slice | Creates a slice of array from start up to, but not including, end. Note: This function is used instead of Array#slice to support node lists in IE < 9 and to ensure dense arrays are returned. |
sortedLastIndex | This method is like _.sortedIndex except that it returns the highest index at which value should be inserted into array in order to maintain its sort order. |
takeRight | Creates a slice of array with n elements taken from the end. |
takeRightWhile | Creates a slice of array with elements taken from the end. Elements are taken until predicate returns falsey. The predicate is bound to thisArg and invoked with three arguments; (value, index, array). |
takeWhile | Creates a slice of array with elements taken from the beginning. Elements are taken until predicate returns falsey. The predicate is bound to thisArg and invoked with three arguments; (value, index, array). |
| Name | Description |
|---|---|
ary | Used to compose bitmasks for wrapper metadata. |
before | Used as the TypeError message for "Functions" methods. |
curryRight | Used to compose bitmasks for wrapper metadata. |
flow | Used as the TypeError message for "Functions" methods. |
negate | Used as the TypeError message for "Functions" methods. |
rearg | Used to compose bitmasks for wrapper metadata. |
| Name | Description |
|---|---|
isError | Object#toString result references. |
isMatch | Used for native method references. |
isNative | Object#toString result references. |
isTypedArray | Object#toString result references. |
toPlainObject | Converts value to a plain object flattening inherited enumerable properties of value to own properties of the plain object. |
| Name | Description |
|---|---|
attempt | Attempts to invoke func, returning either the result or the caught error object. |
matches | Creates a function which performs a deep comparison between a given object and source, returning true if the given object has equivalent property values, else false. |
propertyOf | The inverse of _.property; this method creates a function which returns the property value of a given key on object. |
| Name | Description |
|---|---|
partition | Creates an array of elements split into two groups, the first of which contains elements predicate returns truthy for, while the second of which contains elements predicate returns falsey for. The predicate is bound to thisArg and invoked with three arguments; (value, index |
sortByAll | This method is like _.sortBy except that it sorts by property names instead of an iteratee function. |
| Name | Description |
|---|---|
keysIn | Used for native method references. |
valuesIn | Creates an array of the own and inherited enumerable property values of object. Note: Non-object values are coerced to objects. |
| Name | Description |
|---|---|
thru | This method is like _.tap except that it returns the result of interceptor. |
Version 3 is the biggest update to Lo-Dash ever. With ever increasing user base, modular code base, and cross-browser compatibility, Lo-Dash is the go-to utility library for years to come. With that in mind, there is an going competition with lazy.js and undescore.js, both of which are in active development.