背景
从关于invoke方法的文档中,我读到:
在集合中的每个元素上调用由methodName命名的方法,返回每个被调用方法的结果数组
因此,我假设以下代码是同义的,但事实并非如此:
_.map(items, function(item) {
return _.omit(item, 'fieldName');
})
_.invoke(items, _.omit, 'fieldName');
在这种情况下,invoke
方法生成一个字符串数组,而map方法返回一个从每个项中删除fieldName
的项数组。
问题
- 如何使用
invoke
方法来获得与map
函数相同的结果 - 为什么
invoke
在这种特殊情况下返回字符串数组
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>
确保注意您使用的是哪种版本的lodash。
v4.11.1在对集合进行操作时使用_.invokeMap
:
_.invokeMap([1,2,3], function () {
console.log(this)
})
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
,因为函数应用于项。
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
即可。
正如Joe Frambach所建议的,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' }
// ]