使用javascript .bind()方法跳过参数

时间:2015-09-03 02:59:34

标签: javascript

在JavaScript中,我可以将参数绑定到类似的函数..

function foo(arg1, arg2) { console.log(arguments); }
foo = foo.bind(this, 'bar');

调用时,我们得到这个输出......

foo('baz');
> { '0': 'bar', '1': 'baz' }

是否可以跳过.bind()函数中的参数来实现以下输出?

function foo(arg1, arg2, arg3, arg4) { console.log(arguments); }
foo = foo.bind(this, 'bar', null, 'qux');
foo('baz', 'lel');
> { '0': 'bar', '1': 'baz', '2': 'lel', '3': 'qux' }

4 个答案:

答案 0 :(得分:4)

看看Underscore的_.partial

  

通过填充任意数量的参数来部分应用函数,而不更改其动态此值。 您可以在参数列表中传递_以指定不应预先填充的参数,但在通话时保持打开状态。

在你的情况下:

function foo(arg1, arg2, arg3, arg4) { console.log(arguments); }
foo = _.partial(foo, 'bar', _, 'qux');
foo('baz', 'lel');
> { '0': 'bar', '1': 'baz', '3': 'qux', '4': 'lel'}

是的,我知道这不完全是你所说的。您似乎希望两个参数都被挤入_所在的位置。除了明确指定在调用时将填充两个参数时,没有其他方法:

foo = _.partial(foo, 'bar', _, _, 'qux');

我不一定建议你使用它,但至少你可以看看他们的代码并获得一些提示。

如果您希望最终得到预定的参数,例如'qux',您将需要一些额外的机制。例如,这里有一个小例程(使用ES6,但你可以适应),它将一个函数转换为一个函数,其中指定的参数放在参数列表的末尾:

function partialEnd(fn, ...predefinedArgs) {
  return function() {
    return fn.apply(this, [...arguments, ...predefinedArgs]);
  };
}

你可以这样使用:

function foo(a, b, c) { console.log(a + b + c); }
foo = partialEnd(foo, 3);
foo(1, 2) // outputs 6

您可以使用_.partial占位符将其与_结合使用,以获得将某些参数插入参数列表的效果,其他参数始终放在最后:

function foo(arg1, arg2, arg3, arg4) { console.log(arguments); }
foo = _.partial(foo, 'bar', _, _);
foo = partialEnd(foo, 'lel');

foo('baz', 'lel');
> { '0': 'bar', '1': 'baz', '3': 'lel', '4': 'qux'}

答案 1 :(得分:2)

JavaScript中不存在此类功能,但实现执行相同操作的功能相当简单:

function curryWithNulls(fn, thisObj) {
  var curriedArgs = Array.prototype.slice.call(arguments, 2);
  var length = curriedArgs.length;

  return function() {
    var args = Array.prototype.slice.call(arguments);

    for (var i = 0; i < length || args.length; i++) {
      if (i >= length || curriedArgs[i] === null) {
        curriedArgs[i] = args.shift();
      }
    }
    return fn.apply(thisObj, curriedArgs);
  }
}

function foo(arg1, arg2, arg3, arg4) {
  console.log(arguments);
}

var curriedFoo = curryWithNulls(foo, this, 'bar', null, null, 'qux');
curriedFoo('baz', 'lel');
// => { '0': 'bar', '1': 'baz', '2': 'lel', '3': 'qux' }

这与您的示例稍有不同,因为它需要为每个跳过的参数null(而在您的示例中,您为两个参数填充了一个null)。这允许在任何位置使用curried参数进行更复杂的构造,例如:

var curriedFoo2 = curryWithNulls(foo, this, null, 'bar', null, 'qux');
curriedFoo2('baz', 'lel');
// => { '0': 'baz', '1': 'bar', '2': 'lel', '3': 'qux' }

答案 2 :(得分:0)

不,你只是绑定null

函数的参数是函数的参数;绑定一个null就是这样,它没有重新定义函数,它返回一个具有相同签名的新函数。

答案 3 :(得分:0)

可以使用功能组合:

var foo = function(arg1, arg2, arg3, arg4) { console.log(arguments); }
var bar = function(arg2, arg4) { 
    return foo.bind(this, 'bar', arg2, 'qux')();
}
bar('baz', 'lel');

或者,用现代语法:

const foo = (arg1, arg2, arg3, arg4) => console.log(arguments);
const bar = (arg2, arg4) => foo.bind(this, 'bar', arg2, 'qux')();
bar('baz', 'lel');

或根本没有绑定:

const foo = (arg1, arg2, arg3, arg4) => console.log(arguments);
const bar = (arg2, arg4) => foo(this, 'bar', arg2, 'qux', arg4);
bar('baz', 'lel');

P.S。不要忘记调用绑定的函数(在绑定后注意这些());