javascript - 有人可以帮我编写和理解部分应用程序模式吗?

标签 javascript function functional-programming higher-order-functions partial-application

我试图编写一个利用回调来模仿此行为的函数:

var fullName = function (firstName, lastName) {
  return firstName + ' ' + lastName;
};

var michaelName = partial(fullName, 'Michael');
michaelName('Moore'); // 'Michael Moore'
michaelName('Jackson'); // 'Michael Jackson'


我被困了一段时间,试图编写一个名为partial的函数,该函数将回调该函数fullName,但最终使它起作用,但不确定它是(a)正确的,还是(b)到底在发生什么。

var partial = function(callback, firstName) {
    var innerFunction = function(lastName) { //I declared an inner function in order to create a closure of the variable lastName
      return callback(firstName, lastName); //The closure is completed (or is it only then created?) by returning the function argument named callback taking firstName and lastName as arguments
    };
    return innerFunction; //the function partial will finally return the closure, function innerFunction
}

var michaelName = partial(fullName, 'Michael');
console.log(michaelName('Moore')); //Michael Moore


我在定义函数partial中编写的内容是编写回调的一般模式吗?如果没有,有人可以显示/指出我在哪里可以学习这种模式?还有其他方法可以重构此回调以使其更干净吗?我不确定是否需要创建一个新的innerFunction,但是当我这样做时,我终于使行为按预期工作了。我在代码注释中的推理是否正确?有人会介意逐步检查我的代码并进一步解释正在发生的事情吗,为什么从callback返回innerFunction以及为什么partial返回innerFunction而不是callback?非常感谢。

最佳答案

是的,您已编写partial功能完全正确。

我会避免在此处使用“回调”一词来混淆自己。该词通常在不同的上下文中使用:表示完成某事后调用的例程,或者例如由forEach为数组的每个元素调用的例程。在这里,您传递的只是一个基础函数,当调用返回的函数时,该函数将与一个额外的指定参数一起被调用。您也可以直接返回该函数

var partial = function(fn, firstName) {
    return function(lastName) {
        return fn(firstName, lastName);
    };
}



  还有其他方法可以重构此回调以使其更干净吗?


除了上面提到的以外,不是真的。但是,可以使其更通用(请参见下文)。


  我不确定是否需要创建一个新的innerFunction,但是当我这样做时,我终于使行为按预期工作了。


根据定义,partial需要返回一个函数。这就是它的目的。是的,您必须创建要返回的函数。您可以将其创建为单独的命名函数,然后像您一样将其返回,或者直接在return语句中创建它,如上所述。


  我在代码注释中的推理是否正确?


不是完全:


  我声明了一个内部函数以创建变量lastName的闭包


但是实际上,此函数正在关闭firstName(外部作用域中的变量)。


  通过返回以firstName和lastName作为参数的名为callback的函数参数来完成关闭(或仅是随后创建?)


关于封闭的确切含义,不同的人有不同的想法。有人会说,仅使用外部作用域中的变量定义函数就构成了闭包。其他人会说它不是一个闭包,或者至少称它为闭包是没有意义的,除非像您所做的那样,从外部使用“导出”(返回)该函数以供使用。


  有人会介意逐步检查我的代码并进一步解释正在发生的事情吗,为什么从callback返回innerFunction以及为什么partial返回innerFunction而不是callback


callback不是从innerFunction返回的;调用它的结果是。这正是您需要它的工作方式:您希望partial返回的函数调用您最初传入的函数。直接从callback返回partial不会完成任何操作;而是直接从fullName返回。您将只返回您传入的函数。

因此,总体流程为:


您有一些像partial这样的函数,并且您想要创建另一个函数,该函数的第一个参数为“已经填充”。
定义函数partial,该函数需要一个函数来填充其参数,并填充参数。
partial“记住”要调用的函数,并将要填写的参数传递给它。它返回一个函数(这就是您想要的)
您调用从innerFunction返回的部分函数,​​该函数使用预填充的参数调用原始函数,然后再将另一个函数传递给该函数。该函数(您的callback)可以“看到”要调用的函数(您称为this)和要填充的参数,因为它关闭了它们(这是从外部范围访问那些变量的闭包。


但是,您的偏颇有些局限。一方面,它仅处理一个预填充的参数。您可能想处理更多。另外,它也不知道如何通过innerFunction传递到prefilledArgs。您可以通过以下方法解决此类问题:

function partial(fn, ...prefilledArgs) {
    return function(...additionalArgs) {
        return fn.call(this, ...prefilledArgs, ...additionalArgs);
    };
}


在上面,我使用了新的ES6“扩展参数”功能,因为它更易于读写。在ES5中,您需要使用数组函数将预先填充的参数和其他参数拼接在一起,这并不太有趣,如下所示:

function partial(fn)
    var prefilledArgs = Array.prototype.slice.call(arguments, 1);
    return function() {
        var additionalArgs = Array.prototype.slice.call(arguments);
            return fn.apply(this, prefilledArgs.concat(additionalArgs));
    };
}


在上面的代码中,通过使用fn删除参数伪数组的第一个元素(slice),我们“记住”了预填充的参数并将它们分配给变量apply。然后,在内部函数内部,我们连接预填充的参数和其他参数,然后使用将整个列表传递给原始函数,这是在数组中包含参数时调用函数的方法。

关于javascript - 有人可以帮我编写和理解部分应用程序模式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29788813/

相关文章:

c++ - 多个函数和返回值的问题

oop - 面向对象程序员的方案

javascript - 使用js从页面选项卡查找当前页面

python - 使用当前类实例的属性作为方法参数的默认值

javascript - CSS 应用于所有元素,而不仅仅是类

r - 在函数中使用 dplyr group_by

scala - 将此迭代解决方案转换为函数解决方案

python - <lambda>() 缺少 1 个必需的位置参数 : 'z' with lambda and reduce

javascript - 什么更有效率 : listeners or functions in jquery

javascript - Redux 初始状态在操作时消失