如何在 JavaScript 函数调用中预设参数?(部分功能应用)

IT技术 javascript functional-programming
2021-03-12 04:55:02

我正在尝试编写一个 JavaScript 函数,该函数将返回其第一个参数(函数)及其所有其余参数作为该函数的预设参数。

所以:

函数输出(a,b){
    document.write(a + " " + b);
}

函数 setter(...) {...}

二传手(出,“你好”)(“世界”);
二传手(出,“你好”,“世界”)();

将输出“hello world”两次。对于 setter 的一些实现

我在第一次尝试时遇到了操作参数数组的问题,但似乎有更好的方法来做到这一点。

6个回答

首先,你需要一个部分 -部分和咖喱之间有区别- 这是你需要的一切,没有框架

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}

现在,使用您的示例,您可以完全按照您的要求进行操作:

partial(out, "hello")("world");
partial(out, "hello", "world")();

// and here is my own extended example
var sayHelloTo = partial(out, "Hello");
sayHelloTo("World");
sayHelloTo("Alex");

partial()函数可用于实现,但不是柯里化。这是一篇关于差异的博客文章的引述

在部分应用程序接受一个函数并从中构建一个接受较少参数的函数的情况下,柯里化通过组合每个接受一个参数的函数来构建接受多个参数的函数。

希望有帮助。

完成 - 并没有真正超越您的非返回示例函数,所以我最初忽略了它。谢谢。
2021-04-17 04:55:02
我投票赞成你的答案只是因为我之前已经搜索过一些东西来做这件事。
2021-04-25 04:55:02
你能编辑这个吗?func.apply(this, allArguments) 需要返回 func.apply(this, allArguments)
2021-05-02 04:55:02
Function.prototype.pass = function(){ var args=arguments, func = this; return function(){ func.apply(this,args);} };
2021-05-03 04:55:02
@MuhammadUmer 您应该将其作为答案发布在此页面上。我喜欢它的简单。
2021-05-14 04:55:02

使用 Javascript 的apply(),您可以修改function prototype

Function.prototype.pass = function() {
    var args = arguments,
        func = this;
    return function() {
        func.apply(this, args);
    }
};

然后您可以将其称为 out.pass('hello','world')

apply 接受一个数组作为第二个参数/参数。

arguments 是函数内部可用的属性,它包含数组状结构中的所有参数。

另一种常见的方法是使用 bind

loadedFunc = func.bind(this, v1, v2, v3);

然后

loadedFunc() === this.func(v1,v2,v3);

这样就够了,虽然有点丑。

我认为你应该添加一个正确的解释这是如何工作的;还应包括 OP 功能的示例。
2021-04-23 04:55:02
我个人认为我只是在大多数情况下使用了绑定,我会添加一个示例来说明如何
2021-04-25 04:55:02
很多人反对为了琐碎的目的而修改基本原型,但这似乎是理想的,在整个代码中保持可读性。
2021-05-03 04:55:02

咖喱的JavaScript你在找什么?

我认为他本身不需要咖喱 - 参见stackoverflow.com/questions/218025/...
2021-04-26 04:55:02
链接不再有效。这是同一个页面吗?crockford.com/javascript/www_svendtofte_com/code/...
2021-05-05 04:55:02

如果您使用 Dojo,您只需调用 dojo.hitch() 即可,它几乎完全符合您的要求。几乎 - 因为它也可以用来打包上下文。但你的例子首先是:

dojo.hitch(out, "hello")("world");
dojo.hitch(out, "hello", "world")();

也:

var A = {
  sep: ", ",
  out: function(a, b){ console.log(a + this.sep + b); }
};

// using functions in context    
dojo.hitch(A, A.out, "hello")("world");
dojo.hitch(A, A.out, "hello", "world")();

// using names in context
dojo.hitch(A, "out", "hello")("world");
dojo.hitch(A, "out", "hello", "world")();

dojo.hitch() 是 Dojo Base 的一部分,所以只要您包含 dojo.js,它就在那里。

另一个通用工具在 dojox.lang.functional.curry module中可用(记录在JavaScript中的函数乐趣与 Dojo 中——只需在此页面上查找“curry”)。具体来说,您可能需要查看 curry() 和 partial()。

curry() 累积参数(如在您的示例中),但有一个区别:只要满足 arity,它就会调用返回值的函数。实施您的示例:

df.curry(out)("hello")("world");
df.curry(out)("hello", "world");

请注意,最后一行的末尾没有“()”——它是自动调用的。

partial() 允许随机替换参数:

df.partial(out, df.arg, "world")("hello");

你可以用Function.prototype.bind()这个。这是 ES5 的补充。

除了设置函数上下文(this值)的常见用例外,它还可以设置部分参数。

function out(a, b) {
  document.write(a + " " + b);
}

function setter(func) {
  return func.bind.apply(func, [window].concat([].slice.call(arguments).slice(1)));
}

setter(out, "hello")("world");
setter(out, "hello", "world")();

我的setter功能其实很简单。最长的部分只是获取参数列表。我会像这样分解代码:

func.bind.apply(func, [window].concat([].slice.call(arguments).slice(1)))
func.bind.apply(                                                        )  // need to use apply to pass multiple arguments as an array to bind()
                func,                                                      // apply needs a context to be run in
                      [window].concat(                                 )   // pass an array of arguments to bind(), starting with window, to be the global context
                                      [].slice.call(arguments).slice(1)    // convert the arguments list to an array, and chop off the initial value

这些浏览器支持它:Chrome 7+、Firefox 4+、IE9+。MDN(在开头链接)虽然有一个 polyfill。