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

sh7euo9m  于 2022-12-25  发布在  Java
关注(0)|答案(8)|浏览(391)

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

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

function setter(...) {...}

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

将输出"hello world"两次。对于setter的某些实现
我在第一次尝试操作arguments数组时遇到了一个问题,但似乎有一种更好的方法可以做到这一点。

uxh89sit

uxh89sit1#

首先,您需要一个部分-there is a difference between a partial and a curry-以下是您所需要的全部内容,* 没有框架 *:

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()函数可以用来实现,但是 * 不是 * currying。下面是a blog post on the difference的一段引文:
partial application接受一个函数,并从它构建一个接受较少参数的函数,currying通过组合每个接受一个参数的函数来构建接受多个参数的函数。

bsxbgnwa

bsxbgnwa2#

使用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);
这就够了,虽然有点丑。

zlhcx6iw

zlhcx6iw4#

如果你使用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.咖喱模块中提供了另一个通用工具(在Functional fun in JavaScript with Dojo中有文档--只需在本页中查找“curry”),特别是curry()和partial()。
咖喱()累积参数(如示例中所示),但有一点不同:只要满足arity,它就调用返回值的函数。实现你的例子:

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

注意,最后一行末尾没有“()”--它是自动调用的。
partial()允许随机替换参数:

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

tf7tbtn25#

你可以用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

以下浏览器支持此功能:chrome7+,firefox4+,IE9+。MDN(链接在开头)有一个polyfill。

6mw9ycah

6mw9ycah6#

在不直接调用函数的情况下(例如等待用户确认时)实现参数预设的简单方法是将函数"修饰"在另一个匿名函数中。
代替:exportFile(docType)
剂量:function(){ return exportFile(docType) }

exdqitrt

exdqitrt7#

编辑:请参见Jason Bunting的回答。这个回答实际上展示了一种链接大量out调用的不太好的方法,而不是一个带有一些参数预设的out调用。如果这个回答实际上有助于解决类似的问题,那么您应该确保使用Jason推荐的apply和call,而不是我想出的使用eval的模糊方法。

好吧...你的out实际上会在这里写很多“undefined”...但是这应该接近你想要的:

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

function getArgString( args, start ) {
    var argStr = "";
    for( var i = start; i < args.length; i++ ) {
        if( argStr != "" ) {
            argStr = argStr + ", ";
        }
        argStr = argStr + "arguments[" + i + "]"
    }
    return argStr;
}

function setter(func) {
    var argStr = getArgString( arguments, 1 );
    eval( "func( " + argStr + ");" );
    var newSettter = function() {
        var argStr = getArgString( arguments, 0 );
        if( argStr == "" ) {
            argStr = "func";
        } else {
            argStr = "func, " + argStr;
        }
        return eval( "setter( " + argStr + ");" );
    }
    return newSettter;
}

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

我可能会把getArgString中的代码移到setter函数本身中......因为我使用了'eval's,所以稍微安全一点。

ycl3bljg

ycl3bljg8#

使用闭包是另一种选择。使用返回其他函数的函数!

相关问题