How does the _.invoke method work in Lodash?
Solution 1
var result = _.invoke(items, fn, extraArgs)
Is equivalent to
var result = [];
for (var i=0; i<items.length; i++) {
result.push( fn.apply(items[i], extraArgs) );
}
So if you want the same result as your map, it would be
_.invoke(items, function() {
return _.omit(this, 'id');
})
The only difference is that item
is not a parameter of the function, instead you need to use this
as the function is applied to the item.
Solution 2
Make sure to note which version of lodash you are using.
v4.11.1 uses _.invokeMap
when operating over a collection:
_.invokeMap([1,2,3], function () {
console.log(this)
})
Solution 3
invoke
calls the function as an instance method.
For example,
[
(new Date()).toString(),
(new Date()).toString(),
(new Date()).toString()
]
can be rewritten as:
_.invoke([new Date(), new Date(), new Date()], 'toString')
It is roughly analogous to map
, where map
is passed a function, but invoke
is passed a method of the instances.
If you really want to make invoke
work for you here, then I guess you could do it like this:
var items = [{id:1, name:'foo'},
{id:2, name:'bar'},
{id:3, name:'baz'},
{id:4, name:'qux'}];
_.invoke(items, function() { return _.omit(this, 'id') });
// => [Object {name="foo"}, Object {name="bar"}, Object {name="baz"}, Object {name="qux"}]
but you shouldn't do that. Just use map
.
Solution 4
As Joe Frambach suggested, map() is better suited for this.
var collection = [
{ id:1, name:'foo' },
{ id:2, name:'bar' },
{ id:3, name:'baz' },
{ id:4, name:'qux' }
];
_.map(collection, _.ary(_.partialRight(_.omit, 'id'), 1));
// →
// [
// { name: 'foo' },
// { name: 'bar' },
// { name: 'baz' },
// { name: 'qux' }
// ]
Pete
Updated on July 23, 2022Comments
-
Pete almost 2 years
Background
From the documentation about the invoke method, I read:
Invokes the method named by methodName on each element in collection, returning an array of the results of each invoked method
Thus, I assumed that the following code would be synonymous, but this is not the case:
_.map(items, function(item) { return _.omit(item, 'fieldName'); }) _.invoke(items, _.omit, 'fieldName');
In this case, the
invoke
method produces an array of strings, while the map method returns an array of items withfieldName
removed from each item.Questions
- How can one use the
invoke
method to achieve the same result as themap
function? - Why did
invoke
return the array of strings in this particular situation?
var items = [{id:1, name:'foo'}, {id:2, name:'bar'}, {id:3, name:'baz'}, {id:4, name:'qux'}]; console.log( _.invoke(items, _.omit, 'id') ); console.log( _.map(items, function(item) { return _.omit(item, 'id'); }) );
<script src="https://getfirebug.com/firebug-lite-debug.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.3.1/lodash.min.js"></script>
- How can one use the