我在更新链式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包装器,但是不知道为什么会发生。
答案 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
是不同的-它需要立即执行,因此结束了链。