我最近听说了 Facebook 的 Immutable.js 库 ( https://github.com/facebook/immutable-js )。我对他们文档中的以下内容感到困惑:
var oddSquares = Immutable.Sequence(1,2,3,4,5,6,7,8)
.filter(x => x % 2).map(x => x * x);
console.log(oddSquares.last());
In this example, no intermediate arrays are ever created, filter is only called twice, and map is only called once
filter怎么只调用两次,map一次?
最佳答案
因为 map 和 filter 的逻辑是关于序列的惰性求值
map
在映射序列上调用的 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(因此它应该被过滤), 然后再次调用过滤器函数以获得 7 % 2 = 1 对于 javascript 为真并将该值作为最后一个值返回而不再调用过滤器函数。
作为帮助理解的附加示例:
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,即最终结果
最后,我们被调用了过滤器函数两次而映射器函数只被调用了一次
关于javascript - Immutable.js - 惰性序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25874826/