欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript普通函数中的this指向判断,箭头函数的this有什么不同?

程序员文章站 2022-04-20 23:13:19
1、普通函数 先说说普通函数中的this,各式各样的情况下判断this的指向,可以说是非常刁钻了。判断的时候,只要记住【this 永远指向调用它的对象,new的时候,指向new出来的对象。】这句话就...

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行,我们发现fun是一个立即执行的函数,它的参数也是一个立即执行的函数。

(function(a,b){return a})(1,2) 执行的结果是1,所以fun实际上是下面这样var fun = (function(a){......})(1)

在fun定义的时候,就已经开始执行了,执行结果如下:

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

当执行到fun(3)的时候,fun中的闭包函数开始执行,传入参数b=3,由于此时调用闭包函数的是fun,所以闭包中的this指向fun,从而得出 this.a + b 的值为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。