如何绑定函数参数而不绑定它?

Imb*_*bue 103 javascript

在Javascript中,如何在不绑定this参数的情况下将参数绑定到函数?

例如:

//Example function.
var c = function(a, b, c, callback) {};

//Bind values 1, 2, and 3 to a, b, and c, leave callback unbound.
var b = c.bind(null, 1, 2, 3); //How can I do this without binding scope?
Run Code Online (Sandbox Code Playgroud)

如何避免必须绑定函数范围的副作用(例如setting this= null)?

编辑:

对困惑感到抱歉.我想绑定参数,然后能够稍后调用绑定函数并使其行为与我调用原始函数并将其传递给绑定参数完全相同:

var x = 'outside object';

var obj = {
  x: 'inside object',
  c: function(a, b, c, callback) {
    console.log(this.x);
  }
};

var b = obj.c.bind(null, 1, 2, 3);

//These should both have exact same output.
obj.c(1, 2, 3, function(){});
b(function(){});

//The following works, but I was hoping there was a better way:
var b = obj.c.bind(obj, 1, 2, 3); //Anyway to make it work without typing obj twice?
Run Code Online (Sandbox Code Playgroud)

我仍然是新人,抱歉这是混乱.

谢谢!

小智 29

您可以这样做,但最好不要将其视为"绑定",因为这是用于设置"this"值的术语.或许可以认为它将参数"包装"成函数?

你要做的是创建一个函数,通过闭包在其中内置所需的参数:

var withWrappedArguments = function(arg1, arg2)
    {
        return function() { ... do your stuff with arg1 and arg2 ... };
    }(actualArg1Value, actualArg2Value);
Run Code Online (Sandbox Code Playgroud)

希望我能在那里得到语法.它的作用是创建一个名为withWrappedArguments()的函数(这是一个迂腐的,它是一个分配给变量的匿名函数),你可以在任何地方随时调用它,并且总是使用actualArg1Value和actualArg2Value以及你想放入的任何其他内容.那里.如果需要,您还可以在通话时接受进一步的参数.秘密是最后一个结束后的括号.这些导致使用传递的值立即执行外部函数,并生成可以在以后调用的内部函数.然后在生成函数时冻结传递的值.

这实际上是绑定的作用,但这样显然包装的参数只是对局部变量的闭包,并且不需要改变它的行为.

  • 请注意,这通常称为"Currying". (12认同)

GOT*_*O 0 22

在ES6中,可以使用rest参数spread运算符轻松完成.

所以我们可以定义一个bindArgs类似的函数bind,除了只绑定参数,但不绑定context(this).

Function.prototype.bindArgs =
    function (...boundArgs)
    {
        const targetFunction = this;
        return function (...args) { return targetFunction.call(this, ...boundArgs, ...args); };
    };
Run Code Online (Sandbox Code Playgroud)

然后,对于指定的函数foo和对象obj,声明

return foo.call(obj, 1, 2, 3, 4);
Run Code Online (Sandbox Code Playgroud)

相当于

let bar = foo.bindArgs(1, 2);
return bar.call(obj, 3, 4);
Run Code Online (Sandbox Code Playgroud)

其中只绑定了第一个和第二个参数bar,同时obj使用了调用中指定的上下文,并在绑定参数后追加了额外的参数.返回值只是转发.

  • 把es6带到桌子上,仍然使用var :( (11认同)
  • @DanielKobe谢谢!传播操作符和休息参数在很久之前就已经在Firefox中实现了`let`和`const`,这在我第一次发布这个时尚未提供.它现在更新了. (7认同)

Ber*_*rgi 16

在本机bind方法this中,结果函数中的值将丢失.但是,您可以轻松地重新编码常见填充程序,而不是使用上下文的参数:

Function.prototype.arg = function() {
    if (typeof this !== "function")
        throw new TypeError("Function.prototype.arg needs to be called on a function");
    var slice = Array.prototype.slice,
        args = slice.call(arguments), 
        fn = this, 
        partial = function() {
            return fn.apply(this, args.concat(slice.call(arguments)));
//                          ^^^^
        };
    partial.prototype = Object.create(this.prototype);
    return partial;
};
Run Code Online (Sandbox Code Playgroud)

  • 不喜欢你必须使用"函数"原型的事实,但它节省了我很多时间和一些丑陋的变通方法.谢谢 (4认同)
  • @jackdbernier:你不必这样做,但我发现它更像是`bind`这样的方法.您可以轻松地将其转换为`function bindArgs(fn){...,args = slice.call(arguments,1); ...}` (3认同)

小智 7

var b = function() {
    return c(1,2,3);
};
Run Code Online (Sandbox Code Playgroud)

  • 在所有这些嘈杂和模棱两可的答案中,这是一个准确而有用的答案。因此+1。也许您可以改进答案的风格,使其在丛林中那些花哨嘈杂的其他地方对肉眼更具吸引力。```const curry = (fn, ...curryArgs) => (...args) => fn(...curryArgs, args)``` (3认同)

Dmi*_*rin 7

一个小小的实现只是为了好玩:

function bindWithoutThis(cb) {
    var bindArgs = Array.prototype.slice.call(arguments, 1);

    return function () {
        var internalArgs = Array.prototype.slice.call(arguments, 0);
        var args = Array.prototype.concat(bindArgs, internalArgs);
        return cb.apply(this, args);
    };
}
Run Code Online (Sandbox Code Playgroud)

如何使用:

function onWriteEnd(evt) {}
var myPersonalWriteEnd = bindWithoutThis(onWriteEnd, "some", "data");
Run Code Online (Sandbox Code Playgroud)


Kev*_*nis 2

很难准确说出您最终想要做什么,因为该示例有点任意,但您可能想研究部分(或柯里化):http://jsbin.com/ifoqoj/1/edit

Function.prototype.partial = function(){
  var fn = this, args = Array.prototype.slice.call(arguments);
  return function(){
    var arg = 0;
    for ( var i = 0; i < args.length && arg < arguments.length; i++ )
      if ( args[i] === undefined )
        args[i] = arguments[arg++];
    return fn.apply(this, args);
  };
};

var c = function(a, b, c, callback) {
  console.log( a, b, c, callback )
};

var b = c.partial(1, 2, 3, undefined);

b(function(){})
Run Code Online (Sandbox Code Playgroud)

John Resig 的文章链接:http://ejohn.org/blog/partial-functions-in-javascript/