下面的函数中,进行了比较(找出)哪个函数调用了它。 如果一个是最嵌套的(内部),则返回一个数字,如果最外部,则执行该函数。
var n = function(digit) {
return function(op) {
return op ? op(digit) : digit;
}
};
这些是分配函数调用的变量。
var zero = n(0);
var one = n(1);
var two = n(2);
var three = n(3);
var four = n(4);
var five = n(5);
var six = n(6);
var seven = n(7);
var eight = n(8);
var nine = n(9);
这是"运算符"功能
function plus(r) { return function(l) { return l + r; }; }
function minus(r) { return function(l) { return l - r; }; }
function times(r) { return function(l) { return l * r; }; }
function dividedBy(r) { return function(l) { return l / r; }; }
这是函数的性能,为了它而写的
one(plus(two())), 3);
seven(times(five())), 35);
four(plus(nine())), 13);
eight(minus(three())), 5);
也就是说,我了解代码的一般工作原理,但我不了解细节,并且我无法有意识地自己编写这样的代码,因为我不了解它的详细工作原理。这就是问题所在。 提前致谢
n
和plus
等返回的函数是调用n
等的参数值的闭包。例如,对于n
:
var n = function(digit) {
return function(op) {
return op ? op(digit) : digit;
}
};
// ...
var one = n(1);
var two = n(2);
所以在two
的情况下,函数n
返回(分配给two
)关闭于调用(2
)的digit
值,所以它以后可以访问它。
代码调用two
可以执行以下两项操作之一:
- 不带参数地调用它:
two()
- 用函数调用它:
two(plus(one()))
如果调用two
时没有参数,op
将被undefined
,因此:
return op ? op(digit) : digit;
变得有效
return digit;
所以这意味着,two()
返回2
.
但是如果你把一个函数传递到two
,它会用2
作为参数调用该函数。这就是像plus
这样的东西出现的地方:
function plus(r) { return function(l) { return l + r; }; }
plus
返回一个在r
上关闭的函数。该函数,当你用一个值 (l
) 调用它时,返回l + r
的结果。
因此,让我们看看实际情况:two(plus(one()))
.评估由内而外,因此:
- 调用
one()
时没有参数,所以它返回1
;现在我们实际上有:two(plus(1))
plus()
与1
一起调用并返回有效function(l) { return l + 1; }
function(l) { return l + r; }
(因为r
是1
);所以现在我们有效地有:two(function(l) { return l + 1; })
two
使用步骤 2 中的函数作为op
调用。由于它被赋予了一个函数,因此two
调用op(2)
并返回其结果。op
(步骤 2 中的函数)返回2 + 1
- 结果是
3
.
这是一个版本,可以更容易地看到发生了什么:
const n = function(digit) {
console.log(`n: creating "digitFn" for ${digit}`);
const digitFn = function(op) {
if (op) {
console.log(`digitFn: evaling op(${digit})`);
const result = op(digit);
console.log(`digitFn: returning ${result}`);
return result;
}
console.log(`digitFn: no "op", returning ${digit}`);
return digit;
};
return digitFn;
};
const plus = function(r) {
console.log(`plus: creating "opFn" for + ${r}`);
const opFn = function(l) {
console.log(`opFn: evaling ${l} + ${r}`);
const result = l + r;
console.log(`opFn: returning ${result}`);
return result;
};
return opFn;
};
console.log("main: Creating `one` and `two`");
const one = n(1);
const two = n(2);
console.log("main: Doing `two(plus(one()))`");
console.log(two(plus(one())));
.as-console-wrapper {
max-height: 100% !important;
}
这整体称为部分应用程序:采用一个接受 N 个参数的函数,"烘焙"其中一个或多个参数以生成一个接受N个参数<函数(因为已经提供了一些参数)。
旁注:因为你会在野外看到这个,所以我只注意到你可能会看到这些写成简洁形式的箭头函数,它们写成这样:(params) => expression
(如果只有一个参数,()
是可选的:param => expression
)。使这些简洁形式的箭头起作用的事实是,箭头(=>
)之后的第一件事不是{
(更多在这里)。调用时,简洁箭头函数计算表达式并返回结果(隐式地,简洁箭头函数中没有return
关键字)。这些一开始可能看起来很复杂和令人生畏,直到你习惯于阅读它们。以下是n
:
// Does exactly what your original `n` does
const n = digit => op => op ? op(digit) : digit;
分解如下:
digit => ____
是n
,它返回表达式的结果____
n
返回的函数op => ____
op ? op(digit) : digit
是函数创建的表达式n
计算
以下是完整列表:
const n = digit => op => op ? op(digit) : digit;
const zero = n(0);
const one = n(1);
const two = n(2);
const three = n(3);
const four = n(4);
const five = n(5);
const six = n(6);
const seven = n(7);
const eight = n(8);
const nine = n(9);
// Do exactly the same thing your original functions do
const plus = r => l => l + r;
const minus = r => l => l - r;
const times = r => l => l * r;
const dividedBy = r => l => l / r;