JavaScript中this指向问题

24 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

前言

javascript中关键字this会在执行上下文中绑定一个对象,并且在不同的执行条件下会绑定不同的对象,简单理解,就是在不同的作用域下使用this调用,this的指向是不同的。

this指向window

什么是全局作用域?比如直接写在script标签中的js中的代码,就是全局作用域。 我们在script下写一个函数打印看看

function foo(){
    console.log(this)
}
foo()

浏览器会打印

image.png

可以知道全局作用域下使用this ,就是指向window。但好像这样说不够通透,这this不是在函数里打印的吗。好像也是,我们基本也不会在全局作用域下直接使用this,都是在函数里调用。

我们这里其实是在全局作用域下调用了函数。所有的函数在被调用时,都会创建一个执行上下文:

  • 这个上下文中记录着函数的调用栈、函数的调用方式、传入的参数信息等;
  • this也是其中的一个属性;

这里可以看出,this是在函数调用时被绑定的一个对象,这里就是一个普通函数的调用,this默认绑定到了window对象上。

this指向某对象

另外一种情况就是this指向到了具体的某对象,这种情况就是函数是通过某个对象来调用的,或者说它时某个对象的内部函数。

const shy={
    name:'the shy',   
    say:function(){
        console.log(this);
    },
    foo:foo
}
shy.say()

我们在这个对象里,定义了一个say方法,然后通过对象.函数方式来调用,那么这个this就是指向shy对象。

image.png

同样的如果我们在对象里在嵌套了一层对象,然后调用内部对象的这个函数,那么这个函数打印的this其实就是这个内部对象,可以看到跟函数实际调用的上层作用域有关。

const shy={
    name:'the shy',   
    say:function(){
        console.log(this);
    },
    foo:foo
}

const ning = {
    name:'the ning',
    shy:shy
}
ning.shy.foo()

image.png

const newNing = shy.foo
newNing()
//Window {window: Window, self: Window, document: document, name: '', location: Location, …}

这里我们把某个函数赋值给某个变量,然后通过这个变量去调用,那么这时候其实是window对象,因为实际函数调用地方并没有形成具体的绑定,所以默认是window。

箭头函数中的this

首先应该知道箭头函数是不会绑定this对象的,所以箭头函数里的this会从上层作用域去寻找,如setTimeout函数,我们先看如果不是箭头函数,情况是什么

const shy={
    name:'the shy',   
    say:function(){
        console.log(this);
        setTimeout(function() {
             console.log('setTimeout-',this);
        }, 500);
    },
    foo:foo
}

image.png 可以看到如果setTimeout函数里,传入的是function函数写法,那么这里面的this就是全局的window对象。因为setTimeout其实就是挂载在window对象上,所以这里this是window。

如果我们把它改成箭头函数,那么结果就是

image.png 可以看到就是指向了它的上层作用域,就是shy对象。

总结

this指向问题也是一个小难点,要自己认真去思考理解,对每个调用处的this一步步分析,得出结论。