有人可以帮助我编写和理解部分应用程序模式吗?
Can somebody help me write and understand the partial application pattern?
我正在尝试使用回调函数编写一个函数来模拟此行为:
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
是编写回调的一般模式吗?如果没有,有人可以 show/point 告诉我在哪里可以研究这种模式吗?有没有其他方法可以重构此回调以使其更清晰?我不确定我是否需要创建一个新的 innerFunction
但当我这样做时,我终于让行为按预期工作。我在代码评论中的推理是否准确?有人介意单步执行我的代码并进一步解释发生了什么,为什么从 innerFunction
返回 callback
以及为什么 partial
returns innerFunction
而不是 callback
?非常感谢。
如果您正在寻找一种更简洁的代码编写方式,我建议您使用 Javascript 闭包。这里有一个link解释closures。
var partial = function( firstName) {
return function(lastName) {
return firstName + " " + lastName
};
}
var michaelName = partial('Michael');
console.log(michaelName('Moore'));
如果您需要更好地了解回调 Youtube 有一些很棒的视频,这里有一个堆栈 post 帮助我理解 Callbacks。
引自 post
In plain English, a callback function is like a Worker who "calls
back" to his Manager when he has completed a Task.
据我了解,您的模式是正确的,尽管您的评论不太正确。这是一个更通用的实现:
var partial = function(fn) {
var appliedArgs = Array.prototype.slice.call(arguments,1);
return function() {
var moreArgs = Array.prototype.slice.call(arguments);
return fn.apply(this,appliedArgs.concat(moreArgs));
}
}
这与您的主要区别在于它允许传入函数(callback
,在您的函数中)具有任意数量的参数,并允许部分应用程序满足任意数量的参数。 .. 只要按顺序应用它们。
(请注意,MDN docs 建议不要以这种方式切片 arguments
...同时还提供了这样做的示例。那里没有双重信息!)
好的,让我们逐步完成您的示例:
首先,声明您的基函数 - fullName()
。那里没有混乱。这个函数有两个参数。部分应用的用处在于,您可能会发现自己现在知道一些参数,但以后才知道其他参数。部分应用程序允许您立即应用一些(因此 'partial application')参数,取回与您的基本函数具有相同效果的函数,但需要更少的参数(因为您已经提供了其他参数)。
接下来,您拨打 var michaelName = partial(fullname,"Michael");
您在这里要求的是 "give me a new function, called michaelName
, that does what fullName
would do if the first parameter were always 'Michael' and I only had to give it the last name"。一旦你理解了这一点,剩下的代码就开始有意义了。
partial()
必须 return 一个函数,而不是一个简单的值,因为这就是您所要求的 - 您传入的回调的一个新的、更简单的版本。那应该是什么功能呢?如果用 'Michael' 调用回调,它应该给出回调的结果以及它给出的任何第二个函数。
这又是你的实现:
var partial = function(callback, firstName) {
var innerFunction = function(lastName) {
return callback(firstName, lastName);
};
return innerFunction;
}
这正是 innerFunction()
的意思。这是一个将已知的 firstName
和新的 lastName
提供给 callback()
然后 return 结果的函数。
是的,您写的 partial
函数完全正确。
我会在这里使用术语 "callback" 来避免混淆。这个词通常在不同的上下文中使用:例如,表示在完成某事时调用的例程,或者通过 forEach
为数组的每个元素调用。在这里,您传入的只是一个底层函数,当 returned 函数被调用时,它将与一个额外指定的参数一起被调用。您也可以 return 直接使用函数
var partial = function(fn, firstName) {
return function(lastName) {
return fn(firstName, lastName);
};
}
Is there any other way to refactor this callback so that it's cleaner?
不是真的,除了上面提到的。但是,它可以更通用(见下文)。
I wasn't sure if I needed to create a new innerFunction
but when I did I finally got the behavior to work as intended.
根据定义,partial
需要 return 一个函数。这就是它的目的。所以,是的,您必须创建要使用的函数 return。您可以将它创建为一个单独的命名函数,然后 return 它,就像您所做的那样,或者像上面那样在 return 语句中创建它。
Is my reasoning in the comments to the code accurate?
不完全是:
I declared an inner function in order to create a closure of the variable lastName
但实际上这个函数正在关闭 firstName
,来自外部作用域的变量。
The closure is completed (or is it only then created?) by returning the function argument named callback taking firstName and lastName as argument
对于闭包的具体含义,不同的人有不同的理解。有人会说仅仅使用来自外部作用域的变量来定义函数就构成了闭包。其他人会说它不是闭包,或者至少称它为闭包没有意义,除非函数是 "exported" (returned) 供外部使用,就像你一样做.
Would somebody mind stepping through my code and further explaining what is happening, why callback
is returned from innerFunction
and why partial
returns innerFunction
instead of callback
?
callback
不是从 innerFunction
return 编辑的; 调用的结果是。这正是您需要它工作的方式:您希望由 partial
编辑的函数 return 调用您最初传入的函数。直接从 partial
返回 callback
将无法完成任何事物;您只需 return 调用您传入的函数。
所以整体流程是:
您有一些类似于 fullName
的函数,您想要创建另一个具有第一个参数 "already filled in".
的函数
定义函数partial
,它接受一个函数来填充参数for,以及要填充的参数。
partial
"remembers" 要调用的函数和要填充的参数传递给它。它 return 是一个函数(这就是你想要的)
您从 partial
调用部分函数 returned,它使用预填充的参数调用原始函数,并将另一个参数传递给该函数。该函数(您的 innerFunction
)可以 "see" 要调用的函数(您所说的 callback
)和要填写的参数,因为它 关闭它们 (这是一个从外部范围访问这些变量的闭包。
不过,你的部分有点局限。一方面,它只处理一个预填充的参数。你可能想要处理更多。此外,它不知道如何通过 this
传递到 innerFunction
。您可以通过以下方式解决此类问题:
function partial(fn, ...prefilledArgs) {
return function(...additionalArgs) {
return fn.call(this, ...prefilledArgs, ...additionalArgs);
};
}
在上面,我使用了新的 ES6 "spread parameters" 特性,因为它更容易读写。在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));
};
}
在上面,我们"remember"预先填充的参数并将它们分配给变量prefilledArgs
,通过删除参数伪数组的第一个元素(fn
)使用 slice
。然后,在内部函数中,我们将预填充的参数和附加参数连接起来,并使用 apply
将整个列表传递给原始函数,这是当参数在一个函数中时调用函数的方式数组。
我正在尝试使用回调函数编写一个函数来模拟此行为:
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
是编写回调的一般模式吗?如果没有,有人可以 show/point 告诉我在哪里可以研究这种模式吗?有没有其他方法可以重构此回调以使其更清晰?我不确定我是否需要创建一个新的 innerFunction
但当我这样做时,我终于让行为按预期工作。我在代码评论中的推理是否准确?有人介意单步执行我的代码并进一步解释发生了什么,为什么从 innerFunction
返回 callback
以及为什么 partial
returns innerFunction
而不是 callback
?非常感谢。
如果您正在寻找一种更简洁的代码编写方式,我建议您使用 Javascript 闭包。这里有一个link解释closures。
var partial = function( firstName) {
return function(lastName) {
return firstName + " " + lastName
};
}
var michaelName = partial('Michael');
console.log(michaelName('Moore'));
如果您需要更好地了解回调 Youtube 有一些很棒的视频,这里有一个堆栈 post 帮助我理解 Callbacks。
引自 post
In plain English, a callback function is like a Worker who "calls back" to his Manager when he has completed a Task.
据我了解,您的模式是正确的,尽管您的评论不太正确。这是一个更通用的实现:
var partial = function(fn) {
var appliedArgs = Array.prototype.slice.call(arguments,1);
return function() {
var moreArgs = Array.prototype.slice.call(arguments);
return fn.apply(this,appliedArgs.concat(moreArgs));
}
}
这与您的主要区别在于它允许传入函数(callback
,在您的函数中)具有任意数量的参数,并允许部分应用程序满足任意数量的参数。 .. 只要按顺序应用它们。
(请注意,MDN docs 建议不要以这种方式切片 arguments
...同时还提供了这样做的示例。那里没有双重信息!)
好的,让我们逐步完成您的示例:
首先,声明您的基函数 - fullName()
。那里没有混乱。这个函数有两个参数。部分应用的用处在于,您可能会发现自己现在知道一些参数,但以后才知道其他参数。部分应用程序允许您立即应用一些(因此 'partial application')参数,取回与您的基本函数具有相同效果的函数,但需要更少的参数(因为您已经提供了其他参数)。
接下来,您拨打 var michaelName = partial(fullname,"Michael");
您在这里要求的是 "give me a new function, called michaelName
, that does what fullName
would do if the first parameter were always 'Michael' and I only had to give it the last name"。一旦你理解了这一点,剩下的代码就开始有意义了。
partial()
必须 return 一个函数,而不是一个简单的值,因为这就是您所要求的 - 您传入的回调的一个新的、更简单的版本。那应该是什么功能呢?如果用 'Michael' 调用回调,它应该给出回调的结果以及它给出的任何第二个函数。
这又是你的实现:
var partial = function(callback, firstName) {
var innerFunction = function(lastName) {
return callback(firstName, lastName);
};
return innerFunction;
}
这正是 innerFunction()
的意思。这是一个将已知的 firstName
和新的 lastName
提供给 callback()
然后 return 结果的函数。
是的,您写的 partial
函数完全正确。
我会在这里使用术语 "callback" 来避免混淆。这个词通常在不同的上下文中使用:例如,表示在完成某事时调用的例程,或者通过 forEach
为数组的每个元素调用。在这里,您传入的只是一个底层函数,当 returned 函数被调用时,它将与一个额外指定的参数一起被调用。您也可以 return 直接使用函数
var partial = function(fn, firstName) {
return function(lastName) {
return fn(firstName, lastName);
};
}
Is there any other way to refactor this callback so that it's cleaner?
不是真的,除了上面提到的。但是,它可以更通用(见下文)。
I wasn't sure if I needed to create a new
innerFunction
but when I did I finally got the behavior to work as intended.
根据定义,partial
需要 return 一个函数。这就是它的目的。所以,是的,您必须创建要使用的函数 return。您可以将它创建为一个单独的命名函数,然后 return 它,就像您所做的那样,或者像上面那样在 return 语句中创建它。
Is my reasoning in the comments to the code accurate?
不完全是:
I declared an inner function in order to create a closure of the variable
lastName
但实际上这个函数正在关闭 firstName
,来自外部作用域的变量。
The closure is completed (or is it only then created?) by returning the function argument named callback taking firstName and lastName as argument
对于闭包的具体含义,不同的人有不同的理解。有人会说仅仅使用来自外部作用域的变量来定义函数就构成了闭包。其他人会说它不是闭包,或者至少称它为闭包没有意义,除非函数是 "exported" (returned) 供外部使用,就像你一样做.
Would somebody mind stepping through my code and further explaining what is happening, why
callback
is returned frominnerFunction
and whypartial
returnsinnerFunction
instead ofcallback
?
callback
不是从 innerFunction
return 编辑的; 调用的结果是。这正是您需要它工作的方式:您希望由 partial
编辑的函数 return 调用您最初传入的函数。直接从 partial
返回 callback
将无法完成任何事物;您只需 return 调用您传入的函数。
所以整体流程是:
您有一些类似于
fullName
的函数,您想要创建另一个具有第一个参数 "already filled in". 的函数
定义函数
partial
,它接受一个函数来填充参数for,以及要填充的参数。partial
"remembers" 要调用的函数和要填充的参数传递给它。它 return 是一个函数(这就是你想要的)您从
partial
调用部分函数 returned,它使用预填充的参数调用原始函数,并将另一个参数传递给该函数。该函数(您的innerFunction
)可以 "see" 要调用的函数(您所说的callback
)和要填写的参数,因为它 关闭它们 (这是一个从外部范围访问这些变量的闭包。
不过,你的部分有点局限。一方面,它只处理一个预填充的参数。你可能想要处理更多。此外,它不知道如何通过 this
传递到 innerFunction
。您可以通过以下方式解决此类问题:
function partial(fn, ...prefilledArgs) {
return function(...additionalArgs) {
return fn.call(this, ...prefilledArgs, ...additionalArgs);
};
}
在上面,我使用了新的 ES6 "spread parameters" 特性,因为它更容易读写。在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));
};
}
在上面,我们"remember"预先填充的参数并将它们分配给变量prefilledArgs
,通过删除参数伪数组的第一个元素(fn
)使用 slice
。然后,在内部函数中,我们将预填充的参数和附加参数连接起来,并使用 apply
将整个列表传递给原始函数,这是当参数在一个函数中时调用函数的方式数组。