以下代码有效,虽然我理解它为什么有效,但我还没有看到它。我认为这是因为所有其他设计模式都要好得多。
我仍然希望看到这个例子作为沿线的警示故事,但我没有。
当然,这很糟糕,尤其是我选择的下面的例子,因为它很清楚它的作用但是:
这种模式叫什么?
它常用吗?
有没有合法的项目使用这种模式?
var add = function container (val) {
addFunc = function f (val, undefined) {
addFunc.total += val;
return addFunc;
};
addFunc.total = 0;
return addFunc(val);
};
alert(add(1)(2)(3).total);
alert(add(1)(2)(33).total);
编辑:变量名称更改,以便代码在IE中工作。
从技术上讲,这可以被认为是链接或封装。
当您可以无限期地执行原始功能的一组操作时链接。当你可以链接调用以设置原始选择器的属性和属性时,jQuery使用这种形式。在这种情况下,创建者希望能够将调用链接添加而无需重新键入函数名称。不是最干净的想法,但有效。
此外,由于代码的实际主体永远不会暴露给调用者,因此也可以将其视为封装 addFunc
方法不暴露在外部范围内。
这是一个函数式编程概念 柯里。
基本上,给定一个 function foo(a, b, c)
你创造了一个 function bar(a)
返回 function bar2(b)
返回 function bar3(c)
给出了最终答案。
从技术上讲,这不是真正的currying,因为它无限地进行并使用副作用( total
打破无限循环。
但无论如何,这种模式可以有用。它对于遍历树结构特别有用,在树结构中,您计算树的每个叶子的某些结果,其中结果取决于该叶子的祖先。您在根节点上运行curried函数,然后在每个子节点上运行返回的函数,然后为每个子节点运行等等。如果正在运行的节点有子节点,则纯咖喱函数将返回另一个函数,并且如果你到达了一片叶子,它将返回所需的值。
代码将是一个简单的递归函数,它向自己传递一个新的“根”节点和用它来解析它的函数,它总是需要一个参数。
但是,它在这里使用的方式看起来更像是一种学习练习,而不是一些有用的东西。
编辑:如果你想使它成为一个纯粹的currying函数但仍然具有准无限递归,输入数据需要提供停止信息(就像一个C字符串使用该值 0x00
界定 EOF
):
var add = (function() {
var total = 0;
return function nextAdd(a) {
if(a != null) {
total += a;
return nextAdd;
} else {
return total;
}
};
})();
然后, add(1)(2)(3)(null) === 6
而且没有 .total
副作用参数。
这叫做Currying 维基百科。来自Haskell Curry的名字 维基百科 (但最初是由MosesIlyichSchönfinkel开发的 维基百科 )。
一种转换函数的技术,该函数采用多个参数(或参数的n元组),使得它可以被称为一个函数链,每个函数都有一个参数(部分应用程序)。
从 JavaScript模式 表格2010:
何时使用Currying - 当您发现自己调用相同的函数并传递大部分相同的参数时,该函数可能是一个很好的候选者。您可以通过将一组参数应用于函数来动态创建新函数。新函数将保留重复的参数(因此您不必每次都传递它们),并将使用它们预先填充原始函数所需的完整参数列表。
另一个 咖喱的文章 来自Dustin Diaz。
你可以通过以下方式获得无限好处:
function add() {
var l = arguments.length, i, sum = 0;
for( i=0; i<l; i++) sum += arguments[i];
return sum;
}
alert(add(1,2,3)); // 6
真的,没有理由你要问的代码风格。我没有看到任何合法使用,只是随意的 arguments
长度。