JavaScript 中的 this 究竟指向谁,箭头函数的 this 有什么不同

1、普通函数

先说说普通函数中的this,各式各样的情况下判断this的指向,可以说是非常刁钻了。判断的时候,只要记住【 this 永远指向调用它的对象,new的时候,指向new出来的对象。】这句话就够了。

看几个例子:

 

//例1
var obj = {
    name: 'latency',
    sayName: function(){
        console.log('name:',this.name);
    }
}
obj.sayName()          //name: latency

例1这个例子很好理解,sayName() 方法是 obj 调用的,所以其中的this指向obj。

 

//例2
var name = 'cheng';
var obj = {
    name: 'latency',
    sayName: function(){
        return function(){
            console.log('name:',this.name);
        }
    }
}
obj.sayName()()          //name: cheng

在例2中,打印出来对的this.name不是obj的name,而是window对象的name属性。这是因为sayName()函数中有个闭包,闭包中的this指向调用这个闭包的对象,也就是window对象,写成下面这样可能更好理解:

 

var fun = obj.sayName();
fun()                  //name: cheng   fun()方法是window对象调用的,其this指向window对象


接下来看一个复杂一点的例子:

 

//例3
var fun = function (a){
    this.a = a;
    return function(b){
        console.log('a+b:', this.a + b);
    }
}((function(a,b){return a})(1,2))
fun(3)                  //a+b: 4

在例3中,首先要明确fun是什么,仔细看代码第7行,我们发现这里有一个立即执行的函数,它的参数也是一个立即执行的函数。

(function(a,b){return a})(1,2) 执行的结果是1,然后再来看看这个立即执行函数:

var fun = function (a){    //a = 1
    this.a = a;            //this.a = 1, 由于立即执行,这里的this指向window,也就是window.a = 1
    return function(b){
        console.log('a+b:', this.a + b);
    }
}(1)

所以fun实际上是这个立即执行函数的结果,也就是说:

var fun = function(b){
    console.log('a+b:', this.a + b);
}

执行fun(3)时,this依然指向window,window.a + b = 1 + 3 = 4

 

以上是普通函数中的this,下面来看箭头函数中的this。

 

2、箭头函数

对于箭头函数的this,也只需要记住一句话【箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this

上例子,可以把例2改成箭头函数,让它的表现符合我们的预期

 

//例4
var obj = {
    name: 'latency',
    sayName: function(){
        return () => {
            console.log('name:', this.name);
        }
    }
}
obj.sayName()()          //name: latency

在例4中,return的是一个箭头函数,没有把this绑定到自己的内部,使用this时,指向的是上一层的obj。

 

//例5
var name = 'cheng';

function delay(){
    setTimeout(function(){
        console.log('name:', this.name);
    }, 100)
}

function arrowDelay(){
    setTimeout(() => {
        console.log('name:', this.name);
    }, 100)
}

delay.call({name: 'latency'})               //name: cheng
arrowDelay.call({name: 'latency'})      //name: latency

这个例子就可以很清楚的看出箭头函数和普通函数中this的区别。

根据上面两个例子,我们可以总结出,在函数中需要使用闭包的时候,用箭头函数就很方便了,不需要像以前一样使用hack,类似 var context = this;

 

接下来把例1改成箭头函数来实现,看看结果:

 

//例6
var name = 'cheng';
var obj = {
    name: 'latency',
    sayName: () => {
        console.log('name:', this.name) 
    }
}
obj.sayName()       //name: cheng

 

由于sayName()整个函数就是一个箭头函数,没有自己的this,所以this指向的最近一层作用域内的this,也就是window对象。这种情况下,就不适合用箭头函数来实现了。

再看一个例子

 

//例7
var obj = {
    name: 'latency',
    sayName: function(){
        return () => {
          return () => {
            return () => {
              console.log("name:", this.name);
            };
          };
       };
    }
}
obj.sayName()()()()          //name: latency

这个例子可以更好地帮助我们理解【箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this】这句话。这个例子定义了三个箭头函数,它们都没有绑定this到自己的内部,或者说没有改变this的指向,所以this始终指向obj。



 


 

 

 

 

  • 15
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值