Javascript 如何在不绑定 this 的情况下绑定函数参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13851088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to bind function arguments without binding this?
提问by Imbue
In Javascript, how can I bind arguments to a function without binding the thisparameter?
在 Javascript 中,如何将参数绑定到函数而不绑定this参数?
For example:
例如:
//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?
How can I avoid the side-effect of having to bind the function's scope (e.g. setting this= null) as well?
我怎样才能避免必须绑定函数的作用域(例如 setting this= null)的副作用?
Edit:
编辑:
Sorry for the confusion. I want to bind arguments, then be able to call the bound function later and have it behave exactly as if I called the original function and passed it the bound arguments:
对困惑感到抱歉。我想绑定参数,然后能够稍后调用绑定函数并让它的行为完全像我调用原始函数并将绑定参数传递给它:
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?
I'm still new at this, sorry for the confusion.
我还是新手,很抱歉造成混乱。
Thanks!
谢谢!
回答by Ian Nartowicz
You can do this, but best to avoid thinking of it as "binding" since that is the term used for setting the "this" value. Perhaps think of it as "wrapping" the arguments into a function?
您可以这样做,但最好避免将其视为“绑定”,因为这是用于设置“this”值的术语。也许可以将其视为将参数“包装”到函数中?
What you do is create a function that has the desired arguments built into it via closures:
您要做的是创建一个函数,该函数通过闭包内置了所需的参数:
var withWrappedArguments = function(arg1, arg2)
{
return function() { ... do your stuff with arg1 and arg2 ... };
}(actualArg1Value, actualArg2Value);
Hope I got the syntax right there. What it does is create a function called withWrappedArguments() (to be pedantic it is an anonymous function assigned to the variable) that you can call any time any where and will always act with actualArg1Value and actualArg2Value, and anything else you want to put in there. You can also have it accept further arguments at the time of the call if you want. The secret is the parentheses after the final closing brace. These cause the outer function to be immediately executed, with the passed values, and to generate the inner function that can be called later. The passed values are then frozen at the time the function is generated.
希望我在那里得到了语法。它所做的是创建一个名为 withWrappedArguments() 的函数(迂腐它是一个分配给变量的匿名函数),您可以随时随地调用该函数,并且将始终使用 actualArg1Value 和 actualArg2Value 以及您想要放入的任何其他内容那里。如果需要,您还可以让它在调用时接受更多参数。秘密是最后一个右大括号后面的括号。这些导致外部函数立即执行,带有传递的值,并生成可以稍后调用的内部函数。然后在生成函数时冻结传递的值。
This is effectively what bind does, but this way it is explicit that the wrapped arguments are simply closures on local variables, and there is no need to change the behaviour of this.
这实际上是 bind 所做的,但是通过这种方式可以明确包装的参数只是局部变量的闭包,并且不需要更改 this 的行为。
回答by GOTO 0
In ES6, this is easily done using rest parametersin conjunction with the spread operator.
在 ES6 中,这可以通过使用rest 参数和扩展运算符轻松完成。
So we can define a function bindArgsthat works like bind, except that only arguments are bound, but not the context (this).
所以我们可以定义一个bindArgs像 一样工作的函数bind,除了只绑定参数,而不绑定上下文 ( this)。
Function.prototype.bindArgs =
function (...boundArgs)
{
const targetFunction = this;
return function (...args) { return targetFunction.call(this, ...boundArgs, ...args); };
};
Then, for a specified function fooand an object obj, the statement
然后,对于指定的函数foo和对象obj,语句
return foo.call(obj, 1, 2, 3, 4);
is equivalent to
相当于
let bar = foo.bindArgs(1, 2);
return bar.call(obj, 3, 4);
where only the first and second arguments are bound to bar, while the context objspecified in the invocation is used and extra arguments are appended after the bound arguments. The return value is simply forwarded.
其中只有第一个和第二个参数绑定到bar,而obj使用调用中指定的上下文,并在绑定参数之后附加额外的参数。返回值只是简单地转发。
回答by Bergi
In the native bindmethodthe thisvalue in the result function is lost. However, you can easily recode the common shim not to use an argument for the context:
在天然bind方法的this结果中的函数值丢失。但是,您可以轻松地重新编码公共 shim 以不使用上下文的参数:
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;
};
回答by Dmitrii Sorin
One more tiny implementation just for fun:
一个更小的实现只是为了好玩:
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);
};
}
How to use:
如何使用:
function onWriteEnd(evt) {}
var myPersonalWriteEnd = bindWithoutThis(onWriteEnd, "some", "data");
回答by mike
var b = function() {
return c(1,2,3);
};
回答by Kevin Ennis
It's a bit hard to tell exactly what you ultimately want to do because the example is sort of arbitrary, but you may want to look into partials (or currying): http://jsbin.com/ifoqoj/1/edit
很难确切地说出你最终想要做什么,因为这个例子有点武断,但你可能想要研究部分(或柯里化):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(){})
Link to John Resig's article: http://ejohn.org/blog/partial-functions-in-javascript/
链接到 John Resig 的文章:http: //ejohn.org/blog/partial-functions-in-javascript/
回答by Deepak Dixit
May be you want to bind reference of thisin last but your code:-
可能你想最后绑定this 的引用,但你的代码:-
var c = function(a, b, c, callback) {};
var b = c.bind(null, 1, 2, 3);
Already applied binding for instance thisand later you can not change it. What I will suggest that use reference also as a parameter like this:-
已经应用了绑定,例如这个,以后你不能改变它。我建议将引用也用作这样的参数:-
var c = function(a, b, c, callback, ref) {
var self = this ? this : ref;
// Now you can use self just like this in your code
};
var b = c.bind(null, 1, 2, 3),
newRef = this, // or ref whatever you want to apply inside function c()
d = c.bind(callback, newRef);
回答by Barett
An anonymous user posted this additional info:
一位匿名用户发布了以下附加信息:
Building on what has already been provided in this post -- the most elegant solution I've seen is to Curryyour arguments and context:
建立在什么已经在这个岗位提供的-我见过的最优雅的解决方案是咖喱你的论点和语境:
function Class(a, b, c, d){
console.log('@Class #this', this, a, b, c, d);
}
function Context(name){
console.log('@Context', this, name);
this.name = name;
}
var context1 = new Context('One');
var context2 = new Context('Two');
function curryArguments(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function bindContext() {
var additional = Array.prototype.slice.call(arguments, 0);
return fn.apply(this, args.concat(additional));
};
}
var bindContext = curryArguments(Class, 'A', 'B');
bindContext.apply(context1, ['C', 'D']);
bindContext.apply(context2, ['Y', 'Z']);
回答by Joseph Garrone
Well for the exemple you gave, this will do
那么对于你给出的例子,这会做
var b= function(callback){
return obj.c(1,2,3, callback);
};
If you want to guarenty enclosure of the parameters :
如果你想保证参数的外壳:
var b= (function(p1,p2,p3, obj){
var c=obj.c;
return function(callback){
return c.call(obj,p1,p2,p3, callback);
}
})(1,2,3,obj)
But if so you should just stick to your solution:
但如果是这样,你应该坚持你的解决方案:
var b = obj.c.bind(obj, 1, 2, 3);
It's the better way.
这是更好的方法。
回答by Qwerty
Simple like that?
就这么简单?
var b = (cb) => obj.c(1,2,3, cb)
b(function(){}) // insidde object
More general solution:
更通用的解决方案:
function original(a, b, c) { console.log(a, b, c) }
let tied = (...args) => original(1, 2, ...args)
original(1,2,3) // 1 2 3
tied(5,6,7) // 1 2 5

