上述三个方法好是好,能够按照本身的想法将函数的this强制绑定到指定的对象上(除了使用new绑定能够改变硬绑定外),可是硬绑定存在一个问题,就是会下降函数的灵活性,而且在硬绑定以后没法再使用隐式绑定或者显式绑定来修改this的指向。java
在这里,我用的是《你不知道的JavaScript 上》中的软绑定的代码实现:闭包
1 if(!Function.prototype.softBind){ 2 Function.prototype.softBind=function(obj){ 3 var fn=this; 4 var args=Array.prototype.slice.call(arguments,1); 5 var bound=function(){ 6 return fn.apply( 7 (!this||this===(window||global))?obj:this, 8 args.concat.apply(args,arguments) 9 ); 10 }; 11 bound.prototype=Object.create(fn.prototype); 12 return bound; 13 }; 14 }
咱们先来看一下效果,以后再讨论它的实现。app
1 function foo(){ 2 console.log("name: "+this.name); 3 } 4 5 var obj1={name:"obj1"}, 6 obj2={name:"obj2"}, 7 obj3={name:"obj3"}; 8 9 var fooOBJ=foo.softBind(obj1); 10 fooOBJ();//"name: obj1" 在这里软绑定生效了,成功修改了this的指向,将this绑定到了obj1上 11 12 obj2.foo=foo.softBind(obj1); 13 obj2.foo();//"name: obj2" 在这里软绑定的this指向成功被隐式绑定修改了,绑定到了obj2上 14 15 fooOBJ.call(obj3);//"name: obj3" 在这里软绑定的this指向成功被硬绑定修改了,绑定到了obj3上 16 17 setTimeout(obj2.foo,1000);//"name: obj1" 18 /*回调函数至关于一个隐式的传参,若是没有软绑定的话,这里将会应用默认绑定将this绑定到全局环 19 境上,但有软绑定,这里this仍是指向obj1*/
能够看到软绑定生效了。下面咱们来具体看一下 softBind() 的实现。函数
1 var a=2; 2 function foo(){ 3 } 4 foo.a=3; 5 Function.prototype.softBind=function(){ 6 var fn=this; 7 return function(){ 8 console.log(fn.a); 9 } 10 }; 11 Function.prototype.a=4; 12 Function.prototype.softBind.a=5; 13 14 foo.softBind()();//3 15 Function.prototype.softBind()();//4