本文最后更新于:1 天前
this 的定义
JavaScript 函数中的this
关键字与其他语言略有不同,此外,在严格模式和非严格模式之间也会有一些差别
在绝大多数情况下,函数的调用方式决定了this
的值 (运行时绑定)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function baz ( ){ console .log ("baz" ); bar (); }function bar ( ){ console .log ("bar" ); foo (); }function foo ( ){ console .log ("foo" ); }baz ();
要先弄懂调用位置才能更好的理解this
,同时,this
一旦被确定了,就不可以被更改
绑定规则(重要)
根据不同的使用场合,this有不同的值,主要有下面几种情况
默认绑定
无法应用其他规则时使用
1 2 3 4 5 var name = "Jenny" ;function person ( ){ return this .name ; }console .log (person ());
this指向全局对象window
,严格模式下绑定到undefined
隐式绑定
函数还可以作为某个对象的方法调用,这时this
就指这个上级对象
1 2 3 4 5 6 7 8 9 10 function test ( ){ console .log (this .x ); }var obj = {}; obj.x = 1 ; obj.m = test; obj.m = 1 ;
如果是嵌套对象调用,this
依然指向上一级 的对象
1 2 3 4 5 6 7 8 9 10 var o = { a :10 , b :{ fn :function ( ){ console .log (this .a ) } } } o.b .fn ();
一种特殊情况
1 2 3 4 5 6 7 8 9 10 11 12 13 var o ={ a : 10 , b :{ a :12 , fn :function ( ){ console .log (this .a ); console .log (this ); } } }var j = o.b .fn ;j ();
这里的this
是window
,注意:this永远指向最后 调用它的对象,虽然fn函数是对象b的方法,但是该函数最后在全局作用域中执行,所以最终指向window
1 2 3 4 5 6 7 function foo ( ) { console .log (this .a ); }var obj = { a : 2 , foo : foo };var bar = obj.foo ; var a = "oops, global" ; bar ();
为foo函数创建别名bar时发生了隐式丢失,bar函数自动绑定到window
或者undefined
(严格模式)
new 绑定
通过构建函数new
关键字生成一个实例对象,此时this
指向这个实例对象
这和new关键字的原理有关
1 2 3 4 5 6 function test ( ){ this .x = 1 ; }var obj = new test ();console .log (obj.x )
列举一些特殊情况
new
过程中遇到return
一个对象,此时this
指向为返回的对象
1 2 3 4 5 6 7 8 function fn ( ) { this .user = 'xxx' ; return {}; }var a = new fn ();console .log (a.user )
如果返回的不是对象,是基本数据类型,则this
指向为实例对象
1 2 3 4 5 6 7 8 function fn ( ) { this .user = 'xxx' ; return 1 ; }var a = new fn;console .log (a.user );
虽然null也表示对象,但是此时this依然指向实例对象
1 2 3 4 5 6 7 function fn ( ) { this .user = 'xxx' ; return null ; }var a = new fn;console .log (a.user );
显式修改
apply()、call()、bind()
是函数的一个方法,作用是改变函数的调用对象,它的第一个参数就表示改变后的调用对象,因此,这时this
指的就是这第一个参数
1 2 3 4 5 6 7 function foo ( ) { console .log (this .a ); }var obj = { a : 2 };var obj1 = { a : 3 }; foo.call (obj); foo.call (obj1);
硬绑定
硬绑定是指强制把this绑定到某个对象上(除了使用new时)
注意,函数通过 bind() 方法被绑定,它的this将被永久固定
优先级
new > 显式绑定 > 隐式绑定 > 默认绑定
this 特例
1 2 3 4 5 6 function foo (a,b ){ console .log (a,b); }var dmzobj = Object .create (null );var bar = foo.bind (dmzobj,2 );bar (3 );
间接引用
1 2 3 4 5 6 7 8 function foo ( ){ console .log (this .a ); }var a = 2 ;var o = { a : 3 , foo : foo};var p = { a : 4 }; o.foo (); (p.foo = p.foo )();
软绑定
1 2 3 4 5 6 7 8 9 10 11 function foo ( ) { console .log ("name: " + this .name ); }var obj = { name : "obj" }, obj2 = { name : "obj2" }, obj3 = { name : "obj3" };var fooOBJ = foo.softBind (obj);fooOBJ (); fooOBJ.call (obj3);
箭头函数的this
箭头函数没有自己的this
,箭头函数的this
由外层作用域决定,(运行时绑定)
1 2 3 4 5 6 7 8 9 const obj = { sayThis : () => { console .log (this ); } }; obj.sayThis ();const globalSay = obj.sayThis ;globalSay ();
箭头函数不能作为构造函数