除了之前介绍的call,apply和bind等会对this的指向产生影响,箭头函数也会产生影响。
箭头函数作为bind使用的替代者,不仅仅是让代码更简洁,而且可以改变this的指向,让失去this的方法重新找回和this的绑定。
废话不多说,来看个例子
var obj = { count: 0, cool: function(){ console.log(this.count) } } var count = 1; function foo(func){ var count = 2; console.log(this.count+'balabala') //1balabala func(); } obj.cool(); //0 setTimeout(obj.cool,1000); //1 foo(obj.cool); //1下面来分析一下,第一个调用是obj对象调用的,所以this指向obj,所以结果是obj.count.
第二个调用是setTimeout,这个函数在使用方法的时候会在内部新建一个变量接收第一个方法参数,这个时候调用的本身就是函数的一个引用,这种绑定方式是默认绑定,所以this直接指向的是window对象,所以调用的是window.count.
第三个是在方法内部调用,这个也是传参数了,也是把原函数的值传递过去了,所以也是默认绑定,同上。
现在把方法换成箭头函数的方法。
var obj = { count: 0, cool: ()=>{ console.log(this.count) } } var count = 1; function foo(func){ var count = 2; func(); } obj.cool(); //1 setTimeout(obj.cool,1000); //1 foo(obj.cool); //1现在就比较一目了然了,结果都是1,也就是说函数调用的时候this都是指向的window.这就是箭头函数的影响,他放弃了普通this绑定的机制,用当前的此法作用域覆盖了this本来的值。
可以理解为,他继承了cool()函数的this绑定(即当前定义位置的上一层)。
扫描二维码关注公众号,回复:
1506339 查看本文章
为了验证这一观点,下面在运行一组代码:
var obj = { count:0, cool: function coo(){ setTimeout(function(){ this.count++; console.log(this); setTimeout的参数函数,由于会新定义一个变量并调用函数,所以this指向会断掉,进而指向window },1000); } } obj.cool();这个this打印出来,还是window,就和刚才说的一样,默认绑定。
var obj = { count:0, cool: function coo(){ setTimeout(()=>{ this.count++; console.log(this); this继承了cool的词法作用域 },1000); } } obj.cool();
这个this,打印出来会出现obj整个对象,也就是指向了cool的词法作用域。其实就等价于在函数内部加上了self = this.,然后后续的调用都是self去代替this,故会继承外层函数调用的 this 绑定。
更新分界线---------------------------------------------------------------------------------
如果套用两层,那他遵循最近的一层。
function foo(){ return (a) => { //这里的箭头函数继承自foo console.log(this.a); } } var obj1 = { a:2 } var obj2 = { a:3 } var bar = foo.call(obj1); //此时相当于在函数内部定义了self = this,而此时的this就是obj1. bar.call(obj2); //输出是2,不是3foo内部创建的箭头函数会捕获调用foo时的this,箭头函数的绑定无法被修改。记住箭头函数就是根据外层(函数或全局)作用域来决定this的。