请向我解释一下.如果可能的话,这个 Javascript 代码如何逐步工作



下面的函数中,进行了比较(找出)哪个函数调用了它。 如果一个是最嵌套的(内部),则返回一个数字,如果最外部,则执行该函数。

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);

也就是说,我了解代码的一般工作原理,但我不了解细节,并且我无法有意识地自己编写这样的代码,因为我不了解它的详细工作原理。这就是问题所在。 提前致谢

nplus等返回的函数是调用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可以执行以下两项操作之一:

  1. 不带参数地调用它:two()
  2. 用函数调用它: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())).评估由内而外,因此:

  1. 调用one()时没有参数,所以它返回1;现在我们实际上有:
    two(plus(1))
    
  2. plus()1一起调用并返回有效function(l) { return l + 1; }function(l) { return l + r; }(因为r1);所以现在我们有效地有:
    two(function(l) { return l + 1; })
    
  3. two使用步骤 2 中的函数作为op调用。由于它被赋予了一个函数,因此two调用op(2)并返回其结果。
  4. op(步骤 2 中的函数)返回2 + 1
  5. 结果是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;

最新更新