这个例子是从Javascript Allonge这本书上摘下来的。该主题涉及控制流运算符和函数参数的评估。
const or = (a, b) => a || b
const and = (a, b) => a && b
const even = (n) =>
or(n === 0, and(n !== 1, even(n - 2)))
even(42)
//=> Maximum call stack size exceeded.
书中指出,这将导致无限递归。我相信我理解这部分。因为所有的参数都会被求值,即使or()中的a参数为真,b参数仍然会被求值(当or() 函数在even() 下被调用,即)。 and() 也是如此。 even(n - 2) 参数最终将被反复计算,n 为 2、0、-2、-4...
作为一种解决方案,它说可以将匿名函数作为参数传递。
const or = (a, b) => a() || b()
const and = (a, b) => a() && b()
const even = (n) =>
or(() => n === 0, () => and(() => n !== 1, () => even(n - 2)))
even(7)
//=> false
现在我明白了如何重写代码以使用包含原始表达式的匿名函数,但我不明白这种“延迟计算”是如何造成的。因为匿名函数仍然是 or() 和 even() 函数的参数,是什么阻止它们评估并达到与之前代码相同的结果?
最佳答案
Because the anonymous functions are still parameters to the or() and even() functions, what's to prevent them from evaluating and reaching the same outcome as the previous code?
or()
/and()
调用的参数确实被评估了。但它意味着函数表达式被评估(到一个函数)然后传递给or
/and
,而不是真正调用函数。它仅在函数内部从 a()
/b()
调用,并且仅在实际需要时调用(由于运算符的短路) - 那是实际进行递归调用的地方。
顺便说一句,这个概念也被称为 thunk .
关于javascript - Javascript "delay evaluation"想要避免急切评估时如何运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32188435/