Lodash: an introdution
Contents
- Sorry... What?
- But... Why?
- Manipulate arrays
- Manipulate objects
- Other gems
- Questions
Sorry... What?
Sorry... What??
Lodash is...
Aside from awesome -> Marketing stuff:
- "A modern JavaScript utility library delivering modularity, performance & extras." (lodash.com)
- "Lodash is a JS helper library for arrays, strings and objects."
- "Lodash is the equivalent of the Batman’s utility belt for Javascript"
Sorry... What??
Lodash is...
Sorry... What??
The "Why Lodash"
It's functional! (buzz word people [used to?] love)
"Save time by not coding generic functions. Cleaner code. Less lines. Compatible with all browsers."
"Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc."
Sorry... What??
Great documentation with light background, so clearly for frontend people next to windows, but good to bringing light to backend teams.
The "Why Lodash"
But... Why?
But... Why?
- Some colleagues don't know lodash exists and could use it
- Lots of functions -> Curate the most useful ones
- Provide additional explanation / examples (with [hopefully] help from Rubén and Javi)
Manipulate arrays
Manipulate Arrays
Filter items by value
Mutating
Non-Mutating
var array = ['a', 'b', 'c', 'a', 'b', 'c'];
_.pull(array, 'a', 'c');
console.log(array);
// => ['b', 'b']
_.without([2, 1, 2, 3], 1, 2);
// => [3]
Manipulate Arrays
Filter items by predicate
Mutating
Non-Mutating
var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
return n % 2 == 0;
});
console.log(array);
// => [1, 3]
console.log(evens);
// => [2, 4]
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 40, 'active': false }
];
_.filter(users, function(o) { return !o.active; });
// => objects for ['fred']
Manipulate Arrays
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 40, 'active': false }
];
_.filter(users, function(o) { return !o.active; });
// => objects for ['fred']
// The `_.matches` iteratee shorthand.
_.filter(users, { 'age': 36, 'active': true });
// => objects for ['barney']
// The `_.matchesProperty` iteratee shorthand.
_.filter(users, ['active', false]);
// => objects for ['fred']
// The `_.property` iteratee shorthand.
_.filter(users, 'active');
// => objects for ['barney']
_.filter(collection, [predicate=_.identity])
The different flavours for 'predicate'
Manipulate Arrays
Check items for condition
true for all: _.every()
true for one: _.some()
_.every([true, 1, null, 'yes'], Boolean);
// => false
var users = [
{ 'user': 'barney', 'age': 36, 'active': false },
{ 'user': 'fred', 'age': 40, 'active': false }
];
// The `_.matches` iteratee shorthand.
_.every(users, { 'user': 'barney', 'active': false });
// => false
_.some([null, 0, 'yes', false], Boolean);
// => true
var users = [
{ 'user': 'barney', 'active': true },
{ 'user': 'fred', 'active': false }
];
// The `_.matches` iteratee shorthand.
_.some(users, { 'user': 'barney', 'active': false });
// => false
Manipulate Arrays
Sort items
simple: _.sortBy()
need desc? _.orderBy()
var users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 36 },
{ 'user': 'fred', 'age': 40 },
{ 'user': 'barney', 'age': 34 }
];
_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
var users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 34 },
{ 'user': 'fred', 'age': 40 },
{ 'user': 'barney', 'age': 36 }
];
// Sort by `user` in ascending order and by `age` in descending order.
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
Manipulate Arrays
Find element
first: _.find()
last: _.findLast()
var users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 40, 'active': false },
{ 'user': 'pebbles', 'age': 1, 'active': true }
];
_.find(users, function(o) { return o.age < 40; });
// => object for 'barney'
_.findLast(users, function(o) { return o.age < 40; });
// => object for 'pebbles'
Find element index
first: _.findIndex()
last: _.findLastIndex()
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.findIndex(users, function(o) { return o.user == 'barney'; });
// => 0
_.findLastIndex(users, ['active', false]);
// => 2
Manipulate Arrays
Map and reduce
lodash's _.map() is commonly used to get an array of object properties
var users = [
{ 'user': 'barney' },
{ 'user': 'fred' }
];
// The `_.property` iteratee shorthand.
_.map(users, 'user');
// => ['barney', 'fred']
_.map([4, 8], square);
// => [16, 64]
Simple _.map() use
Manipulate Arrays
Map and reduce
_.reduce() as usual
_.reduce([1, 2], function(sum, n) {
return sum + n;
}, 0);
// => 3
_.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
(result[value] || (result[value] = [])).push(key);
return result;
}, {});
// => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
Manipulate Arrays
Convert a 'list' to a 'dictionary'
_.keyBy(): one object for each key
var array = [
{ 'dir': 'left', 'code': 97 },
{ 'dir': 'right', 'code': 100 }
];
_.keyBy(array, function(o) {
return String.fromCharCode(o.code);
});
// => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
_.keyBy(array, 'dir');
// => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
Manipulate Arrays
Convert a 'list' to a 'dictionary'
_.groupBy(): an array for each key
_.groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }
// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }
Manipulate objects
Manipulate Objects
Iterate
Only own properties: _.forOwn
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.forOwn(new Foo, function(value, key) {
console.log(key);
});
// => Logs 'a' then 'b' (iteration order is not guaranteed).
Manipulate Objects
Iterate
Own and inherited properties: _.forIn
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.forIn(new Foo, function(value, key) {
console.log(key);
});
// => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
Manipulate Objects
Generate new objects
All properites except some: _.omit()
var object = { 'a': 1, 'b': '2', 'c': 3 };
_.omit(object, ['a', 'c']);
// => { 'b': '2' }
Only some properties: _.pick() [much faster]
var object = { 'a': 1, 'b': '2', 'c': 3 };
_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }
Also _.omitBy() and _.pickBy()
Manipulate Objects
Generate arrays
Array of keys: _.keys()
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.keys(new Foo);
// => ['a', 'b'] (iteration order is not guaranteed)
Manipulate Objects
Generate arrays
Array of values: _.values()
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.values(new Foo);
// => [1, 2] (iteration order is not guaranteed)
Manipulate Objects
Generate arrays
Map values: _.mapValues()
var users = {
'fred': { 'user': 'fred', 'age': 40 },
'pebbles': { 'user': 'pebbles', 'age': 1 }
};
_.mapValues(users, function(o) { return o.age; });
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
_.mapValues(users, 'age');
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
Manipulate Objects
Generate arrays
Map Keys: _.mapKeys()
_.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
return key + value;
});
// => { 'a1': 1, 'b2': 2 }
Manipulate Objects
Work with properties
_.get()
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// => 3
_.get(object, ['a', '0', 'b', 'c']);
// => 3
_.get(object, 'a.b.c', 'default');
// => 'default'
Get of an unexisting property returns undefined or the default value, instead of throwing an error
Manipulate Objects
Work with properties
_.set()
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5
If the path to set does not exist it is created, instead of throwing an error
Manipulate Objects
Work with properties
Check existence of a path: _.has()
var object = { 'a': { 'b': 2 } };
var other = _.create({ 'a': _.create({ 'b': 2 }) });
_.has(object, 'a');
// => true
_.has(object, 'a.b');
// => true
_.has(object, ['a', 'b']);
// => true
_.has(other, 'a');
// => false
Manipulate Objects
Merge objects
Normal merging of only own properties: _.assign()
function Foo() {
this.a = 1;
}
function Bar() {
this.c = 3;
}
Foo.prototype.b = 2;
Bar.prototype.d = 4;
_.assign({ 'a': 0 }, new Foo, new Bar);
// => { 'a': 1, 'c': 3 }
Existing properties of the first object are overwritten from left to right
Manipulate Objects
Merge objects
Merging of own and inherited properties without overwriting: _.defaults()
_.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
// => { 'a': 1, 'b': 2 }
The first object is considered the defaults. Only the properties that are not defined on it will be overwritten
Other gems
Other gems
Iterate a number of times
_.times(n, [iteratee=_.identity])
// 1. Basic for loop.
for(var i = 0; i < 5; i++) {
// ....
}
// 2. Using Array's join and split methods
Array.apply(null, Array(5)).forEach(function(){
// ...
});
// Lodash
_.times(5, function(){
// ...
});
Other gems
Debouncing (delay execution of a function)
_.debounce(func, [wait=0], [options={}])
$(window)
.on('scroll', _.debounce(scrollFunc, 1000));
scrollFunc will not be called until 1 second after scrolling has completed.
Other gems
Remove tildes, accents, etc... From a string
_.deburr([string=''])
_.deburr('déjà vu');
// => 'deja vu'
Removes all “combining diacritical marks”. 'Rubén' becomes 'Ruben'.
Great for sorting/searching.
Other gems
Deep clone
_.cloneDeep(value)
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
Functions to do this in plain JS are messy and/or hacky:
var cloned = JSON.parse(JSON.stringify(objectToClone));
Other gems
Math methods
_.maxBy(array, [iteratee=_.identity])
var objects = [{ 'n': 1 }, { 'n': 2 }];
_.maxBy(objects, 'n');
// => { 'n': 2 }
_.meanBy(array, [iteratee=_.identity])
var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
_.meanBy(objects, 'n');
// => 5
_.sumBy(array)
var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
_.sumBy(objects, 'n');
// => 20
Questions?
Okay... I think it's enough, much more in https://lodash.com/docs/
Lodash introduction
By Hector Pablos
Lodash introduction
- 1,898