我尝试对javascript的bind()如何工作进行排序。
如果我这样做,我会看到
var f = function (a) { ... }
var g = f.bind(obj);
g(1)
然后使用obj
将this
和1
称为a
来调用f。
我认为g是围绕f。
的包装函数但是当我做的时候
var f = function (a) { ... }
var g = f.bind(obj);
g.call(1)
然后调用f 1
为this
且a
未定义。
所以看起来g不仅仅是一个简单的包装器,而且call
以某种方式区分了普通函数和绑定函数。
还有一件事是我不能多次部分应用一个功能。
var f = function (a) { ... }
var g = f.bind(obj);
var h = g.bind(1);
h();
然后调用f obj
为this
且a
未定义。
这种行为的原因是什么?
修改
这个问题中的结构实际上是错误的,看看它们应该是什么样子的接受答案(通常我没有注意到call
和bind
总是需要上下文参数作为第一个论点)。
答案 0 :(得分:40)
将对象绑定到具有bind
的函数后,您无法覆盖它。正如您在MDN documentation中所看到的那样,它清楚地写在规范中:
“bind()函数创建一个新函数(一个绑定函数),它具有相同的函数体(ECMAScript 5术语中的内部调用属性)作为它被调用的函数(绑定函数的目标函数)将此值绑定到bind()的第一个参数,无法覆盖。“
这意味着,如果你这样做:
g.call(1);
在符合规范的浏览器上,您将获得obj
this
而不是1
。
你当然可以绑定多个参数,所以:
var sum = function(a, b, c) { return a + b + c };
var sumAB = sum.bind(null, 1, 5);
var sumC = sumAB.bind(null, 2);
console.log(sumC());
但是上下文对象将始终是第一个bind
指定的对象,因为它不能被覆盖。
为了避免混淆,call的第一个参数是上下文对象(this
),那么你将得到其余的参数。
这意味着:
var obj = { foo: function(bar) { console.log(bar) } };
obj.foo('hello');
// equivalent to:
var foo = obj.foo;
foo.call(obj, 'hello');
希望它有所帮助。
答案 1 :(得分:3)
你从未传递任何参数 - 你只设置了上下文。 call
的第一个参数作为上下文(this
)被接收,并且参数2以后作为被调用函数的参数1和之后被接收。同时,bind
使用新的上下文创建一个新函数 - 在调用时传递参数。
以下是从第一个代码块传递1
作为函数f
的参数a
的方法:
f( 1 );
g( 1 );
g.call( this, 1 );
g.apply( this, [ 1 ] );