Releases: lodash/lodash
4.0.0
lodash v4.0.0
2015 was big year! Lodash became the most depended on npm package, passed 1 billion downloads, & its v3 release saw massive adoption!
The year was also one of collaboration, as discussions began on merging Lodash & Underscore. Much of Lodash v4 is proofing out the ideas from those discussions. Lodash v4 would not be possible without the collaboration & contributions of the Underscore core team. In the spirit of merging our teams have blended with several members contributing to both libraries.
For 2016 & lodash v4.0.0 we wanted to cut loose, push forward, & take things up a notch!
Modern only
With v4 we’re breaking free from old projects, old environments, & dropping old IE < 9 support!
4 kB Core
Lodash’s kitchen-sink size will continue to grow as new methods & functionality are added. However, we now offer a 4 kB (gzipped) core build that’s compatible with Backbone v1.2.4 for folks who want Lodash without lugging around the kitchen sink.
More ES6
We’ve continued to embrace ES6 with methods like _.isSymbol, added support for cloning & comparing array buffers, maps, sets, & symbols, converting iterators to arrays, & iterable _(…)
.
In addition, we’ve published an es-build & pulled babel-plugin-lodash into core to make tree-shaking a breeze.
More Modular
Pop quiz! 📣
What category path does the bindAll
method belong to? Is it
A) require('lodash/function/bindAll')
B) require('lodash/utility/bindAll')
C) require('lodash/util/bindAll')
Don’t know? Well, with v4 it doesn’t matter because now module paths are as simple as
var bindAll = require('lodash/bindAll');
We’ve also reduced module complexity making it easier to create smaller bundles. This has helped Lodash adoption with libraries like Async & Redux!
1st Class FP
With v3 we introduced lodash-fp. We learned a lot & with v4 we decided to pull it into core.
Now you can get immutable, auto-curried, iteratee-first, data-last methods as simply as
var _ = require('lodash/fp');
var object = { 'a': 1 };
var source = { 'b': 2 };
var newObject = _.assign(source)(object);
console.log(newObject);
// => { 'a': 1, 'b': 2 }
console.log(object);
// => { 'a': 1 }
var convert = require('lodash/fp/convert');
var assign = convert('assign', require('lodash.assign'));
// works too!
Chakra Optimized
Well actually, while we’re excited about Chakra, Lodash is optimized for great performance across all engines. Unlike many libraries, we don’t favor a single engine so we can deliver solid performance & support regardless of engine.
With v4 we’ve continued our commitment to performance; expanding support for lazy evaluation & improving the performance of core functionality like circular reference detection.
Emojis
Taking things up a notch Lodash v4 has added support for emojis! Includes things like
astral symbols, unicode modifiers, variation selector characters, zero-width joiners, & regional indicator symbols.
Breaking changes
We’ve introduced more breaking changes in this release than any other so 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.
If you dig Lodash don’t forget to star the repo or npm star lodash
!
3.0.0
lodash v3.0.0
After a little over a year & more than 2,000 commits 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 some back-compat breaking changes. We’ll get into that in a bit, but first lets talk about all the cool things this release has to offer.
String methods
By popular demand we surveyed the utility landscape for a cross-section of string APIs to add to lodash. We settled on 17 string methods:
_.camelCase, _.capitalize, _.deburr, _.endsWith, _.escapeRegExp,
_.kebabCase, _.pad, _.padLeft, _.padRight, _.repeat, _.snakeCase,
_.startsWith, _.trim, _.trimLeft, _.trimRight, _.trunc, & _.words
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.
_.camelCase(_.snakeCase(_.kebabCase('fooBar')));
// → 'fooBar'
ES is our jam
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
_.map(['6', '8', '10'], _.parseInt);
// → [6, 8, 10]
_.map(['a', 'a'], ['b', 'b'], _.uniq);
// → [['a'], ['b']]
_.reduce([{ 'b': 2 }, { 'c': 3 }], _.assign, { 'a': 1 });
// → { 'a': 1, 'b': 2, 'c': 3}
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
You can also use individual packages like lodash.ary, lodash.curry, & lodash.rearg to convert functions.
var ary = require('lodash.ary'),
curry = require('lodash.curry'),
rearg = require('lodash.rearg');
var getobject = require('getobject'),
get = curry(rearg(ary(getobject, 2), [1, 0]), 2);
get('a.b.c')({ 'a': { 'b': { 'c': 'foo' } } });
// → 'foo'
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.
var items = [
{ 'value': _.constant(['a', 'b']) },
{ 'value': _.constant(['b', 'c']) }
];
var getValues = _.flow(
_.map(_.result('value')),
_.flatten,
_.uniq
);
getValues(items);
// => ['a', 'b', 'c']
_.map(parseInt)(['6', '08', '10']);
// → [6, 8, 10]
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.
The lodash & lodash-compat npm packages now come with modules baked in too.
Perfect for browserify and webpack!
// 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.
- npm packages for modern, compatibility, & per method builds
- AMD modules for modern & compatibility builds
- ES modules for the modern build
Performance
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.
In v3 we’ve also introduced lazily evaluated chaining for massive performance wins in certain scenarios.
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/B...