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 lodash

lodash is also available in a variety of other builds & module formats.

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.

NameDescription
camelCaseConverts string to camel case. See Wikipedia for more details.
capitalizeCapitalizes the first character of string.
deburrUsed to match latin-1 supplementary letters (excluding mathematical operators).
endsWithChecks if string ends with the given target string.
escapeRegExpUsed to match RegExp special characters. See this article on RegExp characters for more details.
kebabCaseConverts string to kebab case (a.k.a. spinal case). See Wikipedia for more details.
padNative method references.
padLeftPads 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.
padRightPads 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.
repeatNative method references.
snakeCaseConverts string to snake case. See Wikipedia for more details.
startsWithChecks if string starts with the given target string.
trimRemoves leading and trailing whitespace or specified characters from string.
trimLeftRemoves leading whitespace or specified characters from string.
trimRightRemoves trailing whitespace or specified characters from string.
truncUsed as default options for _.trunc.
wordsUsed to match words to create compound words.

NameDescription
chunkNative method references.
dropRightCreates a slice of array with n elements dropped from the end.
dropRightWhileCreates 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).
dropWhileCreates 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).
flattenDeepRecursively flattens a nested array.
pullAtRemoves 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.
sliceCreates 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.
sortedLastIndexThis 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.
takeRightCreates a slice of array with n elements taken from the end.
takeRightWhileCreates 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).
takeWhileCreates 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).

NameDescription
aryUsed to compose bitmasks for wrapper metadata.
beforeUsed as the TypeError message for "Functions" methods.
curryRightUsed to compose bitmasks for wrapper metadata.
flowUsed as the TypeError message for "Functions" methods.
negateUsed as the TypeError message for "Functions" methods.
reargUsed to compose bitmasks for wrapper metadata.

NameDescription
isErrorObject#toString result references.
isMatchUsed for native method references.
isNativeObject#toString result references.
isTypedArrayObject#toString result references.
toPlainObjectConverts value to a plain object flattening inherited enumerable properties of value to own properties of the plain object.

NameDescription
attemptAttempts to invoke func, returning either the result or the caught error object.
matchesCreates 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.
propertyOfThe inverse of _.property; this method creates a function which returns the property value of a given key on object.

NameDescription
partitionCreates 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
sortByAllThis method is like _.sortBy except that it sorts by property names instead of an iteratee function.

NameDescription
keysInUsed for native method references.
valuesInCreates an array of the own and inherited enumerable property values of object. Note: Non-object values are coerced to objects.

NameDescription
thruThis 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.