- _() vs _.chain()
> _([1,2,3,4,5]).map(function (x) { return x * x }).first(3).value()
[ 1, 4, 9 ] // the same if first(3)
> _.chain([1,2,3,4,5]).map(function (x) { return x * x }).first(3).value()
[ 1, 4, 9 ] // the same if first(3)
> _.chain([1,2,3,4,5]).map(function (x) { return x * x }).first()
{ __chain__: true, __wrapped__: 1 } // still a chain.
> _([1,2,3,4,5]).map(function (x) { return x * x }).first()
1 // without param to first, it returns the value directly if _() #weird?
Prefer _.chain()
- Don't _.chain everything
http://jsperf.com/lodash-chain
Chain is 65% slower.
- Prefer _.each instead of native ForEach
_.each is faster because it does less checks, supports sparse array differently.
- function context is optional in most methods.
Instead of _.map(array, module.function.bind(module))
Do _.map(array, module.function, module)
e.g _.map(keys, model.get, model)
- _.pick, _.omit and _.transform
_.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
// → { 'name': 'fred' }
_.omit({ 'name': 'fred', '_userid': 'fred1' }, '_userid');
// → { 'name': 'fred' }
_.transform
var mapped = _.transform({ 'name': 'fred', '_userid': 'fred1' }, function(result, val, key) {
if (key === 'name') {
result[key] = val.toUpperCase();
}
});
// → { 'name': 'FRED' }
-
_.noop
, don't dofunction () {}
-
_.merge vs _.extend
_.merge concats. _.extend replaces.
var names = {
'characters': [
{ 'name': 'barney' },
{ 'name': 'fred' }
]
};
var ages = {
'characters': [
{ 'age': 36 },
{ 'age': 40 }
]
};
_.merge(names, ages);
// → { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
_.extend(names, ages);
// → { 'characters': [{ 'age': 36 }, { 'age': 40 }] }
_.defaults
var customOptions = { 'mysql': { 'host': 'prod.mysql.host' } }
, defaultOptions = { mysql: { 'host': 'localhost', port: '1234'} , redis: true }
_.defaults(customOptions, defaultOptions);
// → {mysql: { 'host': 'prod.mysql.host' }, redis: true}
// Mutates destination object!
customOptions
// → {mysql: { 'host': 'prod.mysql.host' }, redis: true}
_.defaults({}, customOptions, defaultOptions);
_.merge({}, customOptions, defaultOptions);
// → { mysql: { 'host': 'prod.mysql.host', port: '1234'} , redis: true }
- _.any and _.all
.any (.some) .all (.every)
_.any([null, '', undefined, 'something'])
// => true
_.all(['something', 0, true])
// => false
_.all(['something', 'another', true])
// => true
- _.curry vs _.partial
var logABC = function(a, b, c) {
console.log(a + b + c);
}
var curried = _.curry(logABC);
curried(1)(2)(3);
// → 6
function asyncGet(id, joiner, callback) {
request(id, function (response) {
callback(response.body, joiner)
}
}
asyncGet('a', curried, function (a, joiner) {
asyncGet('b', joiner(a), function (b, joiner) {
asyncGet('c', joiner(b), function (c, joiner) {
joiner(c)
})
})
})
// _.partial
asyncGet('a', logABC, function (a, joiner) {
asyncGet('b', _.partial(joiner, a), function (b, joiner) {
asyncGet('c', _.partial(joiner, b), function (c, joiner) {
joiner(c)
})
})
})
_.partial
// instead of
var func2 = obj.func.bind(obj, 'a', b')
// does not alter 'this' context
var func2 = _.partial(obj.func, 'a', 'b')
_.parseInt
vs nativeparseInt
Avoids differences in native ES3 and ES5 parseInt implementations
ES5 removes octal interpretation. ES3 (IE versions 7 & 8)
_.parseInt('080') // 0
// pass in base 10.
_.parseInt('080', 10)
_.template
_.memoize
_.wrap
_.bindAll