Harder, Better, Faster, Stronger Lo-Dash v3

Gajus Kuizinas

Published

Suggest an edit to this post

Lo-Dash is a utility library delivering consistency, customization, performance & extras. It is also one the most dependent upon NPM packages.1 After a complete overhaul (over 800 commits since it has been bumped to v3.0.0-pre2), version 3 boosts increased performance and a whole lot of new features.

3.0.0 version release notes summarize the changes.

Release Date

Lo-Dash 3.0.0 (lodash) has been released on 2015-01-26.3

Download

Version 3.0.0 (2015-01-26) is available from the NPM:

npm install lodash

Module Formats

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

Name

With version 3.0.0, "Lo-Dash" has been renamed to "lodash".45

Breaking Changes

This post focuses on the new features. For breaking changes, refer to the changelog.

Migration

There is a lodash-migrate package that assists with migrating code from older lodash versions to the latest release.

Performance Improvements

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.6

  • Improved overall performance 20-40%.7
  • 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

Custom Builds

The official changelog have not been updated. Until that day, I have summarized the findings8.

Refer to the official changelog.

ES6

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.9

io.js

Lo-Dash is tested and works with io.js.10

Lazy Evaluation

In contrast to eager evaluation, lazy evaluation is an evaluation strategy which delays the evaluation of an expression until it is needed11. 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.

Example

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.

Shortcut Fusion

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.

Deferred Execution

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.

Summary

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.

Added Methods

47 new methods have been added.12 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.

String

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.

Array

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).

Function

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.

Lang

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.

Utility

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.

Collection

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|key, collection).
sortByAll This method is like _.sortBy except that it sorts by property names instead of an iteratee function.

Object

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.

Chain

Name Description
thru This method is like _.tap except that it returns the result of interceptor.

Summary

Version 3 is the biggest update to Lo-Dash ever13. 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.