JS中的this指向|青训营笔记

71 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第4天

this指向一直是经常遇到的问题,特别是在ES6之后,关于this的指向就更加的疑惑,所以今天把this指向整理一下。

普通函数

普通函数的this通常是指向最后调用它的对象的。

看一个例子

const a = {
  name : 'Vicky',
  fn:function(){
    console.log(this.name);
  }
}
a.fn();//Vicky

因为最后调用它的对象是对象a,所以this指向的a

function foo(){
    console.log(this);
}
foo();	//window

这个例子当中相当于是window.foo(),所以this指向的就会是全局对象window。 注:如果是使用的严格模式的话,输出的对象会是undefine

看了这两个例子之后对于this指向最后一个调用它的对象就很清晰明了了。如若第一个例子改成window.a.fn(),输出也是保持不变的,因为最后调用它的对象为a

将第一个例子改变一下:

var name = "Mary";
const a = {
  name : 'Vicky',
  fn:function(){
    console.log(this.name);
  }
}
const foo = a.fn;
foo();//Mary

这是为什么呢,因为在foo = a.fn的时候,fn并没有被调用,而是作为了一个方法赋值给了foo,当foo()的时候,fn才真正被调用,所以相当于window.foo()this指向的是最后调用它的全局变量window

在掘金上还有看到一个大佬写的例子:

var name = "windowsName"; 

function fn() 
{ 
    var name = 'Cherry'; 
    innerFunction(); 
    function innerFunction() 
    { 
        console.log(this.name); // windowsName 
    } 
} 
fn()

\
作者:sunshine小小倩\
链接:https://juejin.cn/post/6844903496253177863\
来源:稀土掘金\
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后输出的是"windowsName",而不是"Cherry",因为虽然innerFunction函数在fn函数里面,但是它在作为函数被调用的时候,没有挂在任何的对象上,也就是说,它在fn函数里被调用时是window.innerFunction()状态的,所以它的this应该指向的是全局对象window

箭头函数

我们都知道,ES6的箭头函数是没有this绑定的,所以它的this指向与普通函数有点差异。

在普通函数里,this的指向是在执行的时候确定的,而不是在函数定义的时候就定下的,它可以根据调用函数执行时候的不同更改this指向

但是在箭头函数里,this的指向是在函数定义的时候定下的,而不是执行时,并且箭头函数this指向要通过它的作用域逐层向上寻找。

可以看一个例子:

var name = "aaa";
var a = {
    name : "bbb",
    foo : function(){
        setTimeout(function(){
            console.log(this.name);//aaa
        },1000)
    }
}
a.foo();

这个是个普通函数,可以发现this是指向window的,和我们的普通函数最后一个例子的原理差不多,相当于setTimeOut里面的匿名函数它在被调用的时候,调用的对象相当于是全局对象window,所以this指向的是window。也可以理解为"匿名函数的this指向永远都是window"。

var name = "aaa";
var a = {
    name : "bbb",
    foo : function(){
        setTimeout(() => {
            console.log(this.name);//bbb
        },1000)
    }
}
a.foo();

箭头函数在函数定义的时候通过查找作用域链,决定this.name的值为"bbb"。

很好理解的就是,箭头函数的this绑定的就是最近一层非箭头函数的this

apply、call、bind

这三个函数都是可以改变this的指向,但是请注意,箭头函数的this是不可更改的,只能改变普通函数的this

联系与区别

  • 三个函数的第一个参数都是指定函数内部的this指向,然后根据指定的作用域,调用该函数。如果为null或者undefine,则this指向全局对象

  • 除了apply第二个参数是传入一个参数数组外,callbind可以直接传入,(第二个参数即调用的函数的参数),如果第二参数为undefine或者null,则表示没有参数传入函数

  • callapply函数可以直接调用执行,但bind函数是返回的一个函数,所以还要再执行一遍,如b.bind(a)()