Array#map
、Array#filter
创建一个新数组,从而有效地迭代该数组(或创建新数组)。
而在 rust、python、java、c# 等中,此类表达式链只会迭代一次。
在大多数情况下,这是无关紧要的,我们不必关心这一点。然而,在某些情况下,性能下降可能会破坏利用
Array
类的函数 api。
如何缓解这种情况?那么您对支持函数表达式延迟求值的库有什么偏好吗?
如果您不希望它迭代多次。您可以使用循环
const numbers = [1,2,3,4,5,6]
let result = 0;
for(const number of numbers) {
const square = number * number
if(square % 2) {
result += square
}
}
console.log(result)
或减少
const numbers = [1,2,3,4,5,6]
const result = numbers.reduce((acc, number) => {
const square = number * number
if(square % 2) {
return acc + square
}
return acc
}, 0)
console.log(result)
数组方法不起作用,因此整个前提是有缺陷的。它们存在于数组对象上的事实意味着它们不像纯函数那样是开放组合。不过你可以再靠近一点
const square = (n) => n * n
const oddNumberOrZero = (n) => n % 2 ? n : 0
const add = (a, b) => a + b
const addOddSquare = (a, b) => add(a, oddNumberOrZero(square(b)))
const reduce = (arr, fn, acc) => arr.reduce(fn,acc)
const numbers = [1,2,3,4,5,6]
const result = reduce(numbers, addOddSquare, 0)
console.log(result)
您似乎也将流畅的界面与函数式编程混为一谈。
您可以从 npm 安装stream-list lib
https://www.npmjs.com/package/stream-list
let myNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let mylist = new List(myNumbers);
myList
.filter((num) => num % 2 == 0) //only pair
.map((num) => num * num) // square
.map((num) => num/2) // half
.toList(); // myNumbers was just itered once
从 ECMAScript 2025 开始,您可以使用 迭代器助手。
示例:
const res = Array(100000000)
.keys() // 0, 1, 2, 3, 4, 5, 6, 7, ...
.map(x => 3*x) // 0, 3, 6, 9, 12, 15, 18, 21, ...
.filter(x => x % 5 == 1) // 6, 21, 36, 51, 66, ...
.take(4) // 6, 21, 36, 51
.reduce((a, b) => a + b) // Sum: 114
console.log(res);
这具有惰性行为:尽管看起来像这样,但并不存在包含 100000000 个元素的数组。初始数组是sparse,只有一个长度属性并且没有条目。它也是该表达式中的 only 数组。
keys
方法返回一个迭代器,它仅被迭代器函数链间接且惰性地消耗。这是最后一个 reduce
调用(这也是一个迭代器方法),它启动了链式迭代器(“管道”)中值的 消费。由于 take(4)
限制了对值的需求,因此 keys()
迭代器及其后面的迭代器仅消耗有限数量的值,因此该函数可以快速完成并得到结果。
请检查以下代码行。 代码中,v * v 除以 2 表示 v 被除。
const numbers = [1,2,3,4,5,6];
const res = numbers.reduce((sum, v)=> sum + (v % 2? v * v: 0), 0);
console.log(res)