因为 map 和 filter 的逻辑对序列的惰性求值
地图
对映射序列调用的last() 返回映射器函数处理的原始序列的last()。
例如:
var mappedSequence = Immutable.Sequence(1,2,3,4,5,6,7,8).map(x => x * x);
console.log(mappedSequence.last());
将输出 64 并且将调用 map 仅一次,因为它所做的唯一事情就是获取原始序列 (8) 的最后一个元素并将其映射到 x => x * x (导致64)
过滤器
last() 在过滤后的序列上调用,将 反向遍历 序列,直到它在序列上找到符合条件的值。所以,例如
var mappedSequence = Immutable.Sequence(1,2,3,4,5,6,7,8).filter(x => x % 2);
console.log(mappedSequence.last());
将输出 7 并且将调用过滤器只调用两次,因为它首先为 8 调用过滤器 (x => x % 2),它返回 0 表示 javascript 的 false(所以应该过滤),然后再次调用 filter 函数以使 7 % 2 = 1 对于 javascript 为 true,并将该值作为最后一个返回,而不再调用 filter 函数。
作为帮助理解的附加示例:
var mappedSequence = Immutable.Sequence(1,2,3,4,6,8).filter(x => x % 2);
console.log(mappedSequence.last());
会调用过滤函数四次,一次为 8(结果为假),一次为 6(再次为假),一次为 4(再次为假),最后为 3(最终为真) )
将两部分放在一起
你的例子:
var oddSquares = Immutable.Sequence(1,2,3,4,5,6,7,8)
.filter(x => x % 2).map(x => x * x);
console.log(oddSquares.last());
- 要获取映射序列的last()值,首先要获取过滤序列的last()值
- 要获得过滤后序列的 last() 值,首先要获得原始序列 (8) 的 last() 值,并再次使用过滤器函数 ( x => x % 2 ) 对其进行评估,调用它第一次
- 由于 8 % 2 = 0,在 JS 上为假,应该被过滤,所以,我们移动到下一个值 (7) 并再次调用过滤函数用这个值
- 7 % 2 = 1,在JS上为真,不应该被过滤,所以,这是过滤后序列的最后一个值
- 我们得到了映射序列所需的最后一个值 (7),因此我们调用映射器函数 (x => x * x)仅一次得到 49,即最终结果
最后,我们会调用过滤器函数两次,而映射器函数只调用一次