_.invoke 方法在 Lodash 中如何工作?

How does the _.invoke method work in Lodash?

背景

从关于 invoke 方法的文档中,我读到:

Invokes the method named by methodName on each element in collection, returning an array of the results of each invoked method

因此,我假设以下代码是同义词,但事实并非如此:

_.map(items, function(item) {
    return _.omit(item, 'fieldName');
})

_.invoke(items, _.omit, 'fieldName');

在这种情况下,invoke 方法生成一个字符串数组,而 map 方法 return 生成一个项目数组,其中 fieldName 从每个项目中删除。

问题

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>

invoke 将函数作为实例方法调用。

例如,

[
(new Date()).toString(),
(new Date()).toString(),
(new Date()).toString()
]

可以改写为:

_.invoke([new Date(), new Date(), new Date()], 'toString')

它大致类似于map,其中map传递了一个函数,但是invoke传递了一个实例的方法。

如果你真的想让 invoke 在这里为你工作,那么我想你可以这样做:

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"}]

但你不应该那样做。只需使用 map.

var result = _.invoke(items, fn, extraArgs)

相当于

var result = [];
for (var i=0; i<items.length; i++) {
  result.push( fn.apply(items[i], extraArgs) );
}

因此,如果您想要与地图相同的结果,那就是

_.invoke(items, function() {
  return _.omit(this, 'id');
})

唯一的区别是 item 不是函数的参数,相反您需要使用 this 因为函数被应用 到项目 .

因为 Joe Frambach suggested, map() 更适合这个。

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' }
// ]

请务必记下您使用的是哪个版本的 lodash。

v4.11.1 在对集合进行操作时使用 _.invokeMap

_.invokeMap([1,2,3], function () {
    console.log(this)
})