为什么Lodash包装器不适用于forEach?

时间:2019-10-04 12:06:46

标签: javascript arrays lodash wrapper

我在更新链式lodash操纵时遇到了这个问题,我不明白为什么它会以不同的方式工作

我将其范围缩小到在lodash包装器上链接forEach

let tab = [{a:1, b:1}, {a:1, b:2}, {a:2, b:1},{a:2, b:2}]
let res = _(tab).forEach(el => {el.c = 3; return el;}).groupBy('a')
console.log(res)

https://jsbin.com/wahokezeja/edit?js,console

这将引发错误:

  

“ TypeError:_(...)。forEach(...)。groupBy不是函数

但是,当与地图链接时,它可以正常工作

let tab = [{a:1, b:1}, {a:1, b:2}, {a:2, b:1},{a:2, b:2}]
let res = _(tab).map(el => {el.c = 3; return el;}).groupBy('a').value()
console.log(res)

https://jsbin.com/mofusel/1/edit?js,console

它与_(tab)有关。forEach返回一个数组,而不是lodash包装器,但是不知道为什么会发生。

1 个答案:

答案 0 :(得分:3)

lodash forEach的行为不完全像JS forEach,但也不完全像map。 _.map([1,2,3],a=>2*a)将返回数组[2,4,6],如您所料,但是_.forEach([1,2,3],a=>a*2)返回[1,2,3]。它旨在对每个数组元素(例如JS [].forEach)执行一个操作,但是它不返回修改后的数组,而是为方便起见返回 original 数组。如果要修改数组,请使用map

尝试以下操作:

var arr=[1,2,3]; 
var rslt=_(arr).forEach(v=>v*2); 
console.log(arr===rslt);

您会看到它返回true-forEach中的“结果”(是否包装)只是原始数组。

深入研究lodash代码和@VLAZ的一些有用注释之后,理解这一点的关键是与链接相关联的惰性评估(这是上面提到的数组包装的要点)。 (包装)链式方法可以进行惰性评估。如果您调用_(array).map(fn1).map(fn2).value(),则在调用value方法之前不会进行求值。这是一个很好的效率改进,因为(在这种情况下)仅生成一个输出数组(与标准的JS map方法不同,它将在每个步骤之后生成中间数组)。但是forEach是不同的-它需要立即执行,因此结束了链。