After a little over a year & more than 2,000commits we’re excited to release lodash v3.0.0. lodash follows semantic versioning so with this major release we’ve taken the opportunity to clean house & make . We’ll get into that in a bit, but first lets talk about all the cool things this release has to offer.
There’s familiar methods from ES5, like _.trim, & ES6, like _.endsWith, _.repeat, & _.startsWith, as well as some lesser known methods like _.deburr & _.kebabCase.
// trims whitespace like `String#trim` but
// also allows specifying characters to trim
_.trim(' abc ');
// → 'abc'
_.trim('-_-abc-_-', '_-');
// → 'abc'
// works great with `_.map` too
_.map([' foo ', ' bar '], _.trim);
// → ['foo', 'bar']
// deburr diacritical marks (http://en.wikipedia.org/wiki/Diacritic)
_.deburr('déjà vu');
// → 'deja vu'
// similar to a `dasherize` or `slugify` method
_.kebabCase('foo bar');
// → 'foo-bar'
Following casing rules with methods like _.camelCase, _.kebabCase, & _.snakeCase allows for strings to be transformed from say camel case, to kebab case, to snake case, & back again.
Previous versions of lodash added _.assign, _.find, _.findIndex, & ES template delimiter support. In this release we’re taking our ES adoption up a notch by aligning _.includes, _.isFinite, & _.keys, supporting typed arrays in _.clone & _.isEqual, using Set & WeakMap for performance-gains, allowing Map & WeakMap to be used as _.memoize.Cache, & supporting ES modularized builds with lodash-cli.
Functional goodies
There’s lots of functional goodies in v3 like _.ary, _.curryRight, _.flow, _.rearg, & support for customizable argument placeholders in _.bind, _.bindKey, _.curry, _.curryRight, _.partial, & _.partialRight.
// infomercial fail
_.map(['6', '8', '10'], parseInt);
// → [6, NaN, 2]
// using a placeholder to pass over the
// `string` parameter & specify a `radix` of `0`
_.map(['6', '8', '10'], _.partial(parseInt, _, 0));
// → [6, 8, 10]
// is equivalent to
_.map(['6', '8', '10'], function(value) {
return parseInt(value, 0);
});
// customize `_.partial.placeholder`
_.partial.placeholder = '_';
_.map(['6', '8', '10'], _.partial(parseInt, '_', 0));
// → [6, 8, 10]
Also several methods now work out-of-the-box as iteratees for methods like _.map & _.reduce
We’ve heard from some functional programming fans that lodash wasn’t functional enough, often citing our method signatures as an issue. To ease composition & currying they’d prefer methods like _.filter be predicate first & collection second instead of collection first & predicate second.
It’d be a shame for those fans to lose out on lodash over something as little as method signatures so with v3 we’ve added _.ary & _.rearg. The _.ary method sets the argument cap of a function & _.rearg rearranges the arguments provided to a function.
// cap the number arguments provided to `parseInt` at one
_.map(['6', '8', '10'], _.ary(parseInt, 1));
// → [6, 8, 10]
// create a `filter` that’s predicate-first
var filter = _.rearg(_.filter, 1, 0);
filter('a', [{ 'a': 0 }, { 'a': 1 }]);
// → [{ 'a': 1 }]
// create an `includes` that’s auto-curried & needle-first
var includes = _(_.includes).ary(2).rearg(1, 0).curry(2).value();
includes(2)([1, 2, 3]);
// → true
Combined with _.runInContext you could easily create a version of lodash with auto-curried iteratee-first methods. In fact, that’s what we’ve done! Introducing lodash-fp.
lodash reduces the cost of method wrapping produced by _.ary, _.curry, & _.rearg by using a WeakMap to store function metadata. In this way a function is only wrapped once even though it may have _.ary, _.curry, & _.rearg applied.
Modules, modules, modules
In lodash v2 we introduced npm packages per-method as well as bundles of modules for AMD & Node.js. With v3 we’ve improved lodash-cli’s ability to inline dependencies allowing us to easily customize inlining per method, enabling a better balance between deep dependency graphs & code duplication.
In addition all modularized dependencies now use the ^ version range, instead of the ~, so they’ll update as needed without you having to worry about it. Moving forward all per-method packages will be independently updated, instead of in bulk, because lodash-cli will soon be able to detect changes in packages & automatically bump patch/minor version numbers.
// load the modern build
var _ = require('lodash');
// or a method category
var array = require('lodash/array');
// or a method
var chunk = require('lodash/array/chunk');
The method modules are organized by category so they’re easy to find.
lodash is available in a variety of other builds & module formats.
We’ve 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.
As mentioned above we’re using Set & WeakMap for performance-gains which all modern browsers, Node.js, & io.js can benefit from.
Breaking changes
lodash v3 is a major bump & we’ve introduced several back-compat breaking changes. One such change is that while we still test against Underscore/Backbone unit tests we’re no longer supporting an Underscore/Backbone build. Over the last year we’ve seen Underscore align more & more with lodash’s API so the need for a separate Underscore build has diminished. If you still need compatibility around some of the edges we recommend leveraging modules in lodash v3 to supplement your Underscore use.
Be sure to check out the changelog for a full rundown of changes & give lodash-migrate a spin to help migrate older lodash code to the latest release.
New Core Member
In closing I want to welcome Benjamin Tan (bnjmnt4n) as an official core member.
Without the efforts of contributors, like Benjamin, lodash v3 would not have happened.
If you dig lodash v3 don't forget to star the repo or npm star lodash!