《你不知道的js》——this全面解析
默认绑定
//全局对象用于默认绑定 function foo(){ console.log(this.a) } var a=2; foo(); //2
//严格模式下,不能将全局对象用于默认绑定 function foo(){ 'use strict'; console.log(this.a) } var a=2; foo(); //TypeError: this is undefined
//在严格模式下调用foo()则不影响默认绑定 function foo(){ console.log(this.a) } var a=2; (function(){ 'use strict'; foo(); })(); //2
隐式绑定
//当函数拥有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象 function foo(){ console.log(this.a) } var obj={ a:2, foo:foo } obj.foo(); //2
//对象属性链中只有上一层或者最后一层在调用位置中起作用 function foo(){ console.log(this.a) } var obj2={ a:42, foo:foo } var obj1={ a:2, obj2:obj2 } obj1.obj2.foo(); //42
//this 被隐式绑定的函数会丢失绑定对象,也就是说会应用默认绑定,从而把this绑定到全局对象或者undefined上 function foo(){ console.log(this.a) } var obj={ a:2, foo:foo } var bar=obj.foo; var a="hello"; bar(); //hello
//参数传递其实就是隐式传递,因此我们传入函数是也会被隐式赋值 function foo(){ console.log(this.a) } function doFoo(fn){ fn(); } var obj={ a:2, foo:foo } var bar=obj.foo; var a="hello"; doFoo(obj.foo) //hello
//回调函数丢失this绑定 function foo(){ console.log(this.a) } var obj={ a:2, foo:foo } var a="hello"; setTimeout(obj.foo,100) //hello
显式绑定
//通过foo.call(..),在调用foo时强制把它的this绑定到obj上 function foo(){ console.log(this.a) } var obj={ a:2 } foo.call(obj) //2
//硬绑定 function foo(){ console.log(this.a) } var obj={ a:2 } var bar=function(){ foo.call(obj) }; bar(); //2 setTimeout(bar,100); //2 //硬绑定的bar 不可能再修改它的this bar.call(window); //2
//硬绑定典型应用场景:创建一个包裹函数,负责接收参数并返回值 function foo(something){ console.log(this.a,something); return this.a + something; } var obj={ a:2 } var bar=function(){ return foo.apply(obj,arguments) } var b=bar(3); //2 3 console.log(b) //5
//硬绑定典型应用场景:创建一个可以重复使用的辅助函数 function foo(something){ console.log(this.a,something); return this.a + something; } //简单的辅助绑定函数 function bind(fn,obj){ return function(){ return fn.apply(obj,arguments) } } var obj={ a:2 } var bar=bind(foo,obj); var b=bar(3); //2 3 console.log(b) //5