Last updated on November 3, 2024 pm
记录一下一些常见场景
(崩溃了,怎么就是看不懂🥹小小this赶紧让我拿下)
this部分参考总结于嗨,你真的懂this吗? · Issue #6 · YvetteLau/Blog
一、this的绑定规则 (1)默认绑定 默认绑定,在不能应用其它绑定规则时使用的默认规则,通常是独立函数调用 。
在非严格模式下,函数内的 this
指向全局对象(浏览器中是 window
,Node.js 中是 global
),除非该函数是作为对象的方法调用。
在严格模式下,如果函数是直接调用(不通过对象调用),this
将会是 undefined
。
浏览器中,使用 var
定义(let不行 )的全局变量(如 name
)会被添加到 window
对象上。
在 Node.js 中,使用 var
定义的全局变量不会自动添加到 global
对象上。相反,它们只能在当前模块的作用域中访问。
global.name = ‘YvetteLau’;只有这样的显示定义才被视为定义
(2)隐式绑定 函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。
1 2 3 4 5 6 7 8 9 function sayHi ( ){ console .log ("hello," ,this .name ); }let person={ name : "Yaoyao" , sayHi : sayHi, }let name="Shenshen" ; person.sayHi ();
对象属性链中只有最后一层会影响到调用位置:
1 2 3 4 5 6 7 8 9 10 11 12 function sayHi ( ){ console .log ("hello," ,this .name ); }let person1={ name : "Yaoyao" , sayHi : sayHi, }let person2={ name : "Shenshen" , friend : person1, } person2.friend .sayHi ();
不是通过对象来进行调用 仍旧是默认指向!!!
1 2 3 4 5 6 7 8 9 10 function sayHi ( ){ console .log ("hello," ,this .name ); }let person={ name : "Yaoyao" , sayHi : sayHi, }var name="Shenshen" ;let Hi =person.sayHi ;Hi ();
在上面的例子中,输出的是Shenshen。因为Hi绑定在sayHi上,调用时和person没有关系
下一个例子:(隐形绑定的丢失会发生在回调函数中)(在浏览器运行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function sayHi ( ){ console .log ("hello," ,this .name ); }let person1={ name : "Yaoyao" , sayHi : function ( ){ setTimeout (function ( ){ console .log ('Hello,' ,this .name ); }) } }let person2={ name : "Shenshen" , sayHi : sayHi }var name="Shanshan" ; person1.sayHi (); setTimeout (person2.sayHi ,1000 ); setTimeout (function ( ){ person2.sayHi (); },1000 );
(在node中运行时就算显式指定global.name的值还是会输出undefined,不知道为什么)
(3)显式绑定 显式绑定的丢失:
1 2 3 4 5 6 7 8 9 10 11 12 function sayHi ( ){ console .log ('Hello,' , this .name ); }var person = { name : 'YvetteLau' , sayHi : sayHi }var name = 'Wiliam' ;var Hi = function (fn ) { fn (); }Hi .call (person, person.sayHi );
这时候,fn是person.sayHi,将this绑定到了Hi的this,但是执行fn的时候相当于直接调用了sayHi方法,此时隐式绑定也丢了,对应的是默认绑定。
解决方法是在调用fn的时候也硬绑定
1 2 3 var Hi = function (fn ) { fn.call (this ); }
如果我们将null或者是undefined作为this的绑定对象传入call、apply或者是bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。
(4)new绑定 使用new来调用函数会自动执行下面的操作:
1、创建一个新对象
2、将构造函数的作用域赋值给新对象(即this指向这个新对象)
3、执行构造函数中的代码
4、返回新对象
1 2 3 4 5 function sayHi (name ){ this .name =name; }var Hi =new sayHi ("Yaoyao" );console .log (Hi .name );
(5)绑定优先级 new绑定>显式绑定>隐式绑定>默认绑定
(6)箭头函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var obj = { hi : function ( ){ console .log (this ); return ()=> { console .log (this ); } }, sayHi : function ( ){ return function ( ) { console .log (this ); return ()=> { console .log (this ); } } }, say : ()=> { console .log (this ); } }let hi = obj.hi (); hi (); let sayHi = obj.sayHi ();let fun1 = sayHi (); fun1 (); obj.say ();
①:通过对象调用函数,属于隐式调用。this指向obj
②:箭头函数是从上一个作用域继承this,所以这时指向的是obj
③:这是上面的隐式绑定丢失的情况,this指向window
④:这一步执行的是箭头函数,继承上一个作用域,this指向window
⑤:当前代码块中obj中不存在this,因此再向上找就找到了window
如果这样去显式绑定:(箭头函数不能显式绑定)
1 2 3 let sayHi=obj.sayHi ();let fun1=sayHi.bind (obj);fun1 ();
(7)例题 1、 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var number = 5 ;var obj = { number : 3 , fn : (function ( ) { var number; this .number *= 2 ; number = number * 2 ; number = 3 ; return function ( ) { var num = this .number ; this .number *= 2 ; console .log (num); number *= 3 ; console .log (number); } })() }var myFun = obj.fn ; myFun.call (null ); obj.fn ();console .log (window .number );
输出结果分别为10、9、3、27、20
2、 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var obj = { a : 'obj' , foo : function ( ) { console .log ('foo:' , this .a ) return function ( ) { console .log ('inner:' , this .a ) } } }var a = 'window' var obj2 = { a : 'obj2' } obj.foo ()() obj.foo .call (obj2)() obj.foo ().call (obj2)
①:分别打印出的是obj.a和window.a
②:分别打印的是obj2.a和window.a
③:分别打印的是obj.a和obj2.a
3、 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var obj = { a : 1 , foo : function (b ) { b = b || this .a return function (c ) { console .log (this .a + b + c) } } }var a = 2 var obj2 = { a : 3 } obj.foo (a).call (obj2, 1 ) obj.foo .call (obj2)(1 )
①:传入foo的参数为a=2,也就是说b=2;call方法将this绑定到obj2,this.a=3,此时c=1
②:foo绑定至obj2,此时没有传入参数,b=this.a=obj2.a=3,return匿名函数中的this.a指向window对象a=2,传入的参数c=1。