上述三個方法好是好,能夠按照本身的想法將函數的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