关于 this 指向的理解

183 阅读3分钟

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

this 的指向一直是面试中频繁出现的考点之一,也是容易混淆的点。不仅包括对于 this 本身的考察,还有如何修改 this 指向,以及ES6 的箭头函数中 this 的特点等等的考察

关于 this

this 是 JavaScript 中的一个关键字,指的是函数运行时所在的环境。它的特点是:

  • 只能在函数内部使用,并且永远指向最后一个调用它的对象
  • this一旦被确定了,就不可以再更改,修改this运行后会报错

在不同的开发场景中,this 绑定的方式也有所不同,总体分为几种:

  • 默认绑定
  • 隐式绑定
  • 显示绑定
  • new绑定

默认绑定

先来看看下面这段代码,就是我们常见的默认绑定

var msg = 'haha'; 
function say() { 
    return this.msg; 
} 
console.log(say()); //msg

say()函数的调用位置为最后一行,也就是window,因此 this 的指向是 window

隐式绑定

隐式绑定时是当函数作为某个对象的方法调用时绑定, this 指向它上一级的对象

    let obj = {
        a:100,
        b:{
            c: 200,
            fn:function(){
                console.log(this.name); // 1.undefined
            }
        }
    }
    obj.b.fn(); // 调用函数fn()的对象是b

上面这段代码,1.处的值为 undefined ,指向它上一级的对象b,而 b 中没有a这个属性,所以是 undefined。

但是还有一个很容易踩坑的地方,我们来看这样一段代码:

    let obj = {
        a:100,
        b:{
            a: 200,
            fn:function(){
                console.log(this); //window
                console.log(this.a); //undefined
            }
        }
    }
    let doSomething = obj.b.fn;
    doSomething();

当对象中声明了函数,调用它的时候结果却指向了window,这是为什么呢?

其实就是上面提到的: this 永远指向最后一个调用它的对象。而最后一个调用它的对象不是b,而是doSomething,(fn赋值给而是doSomething的时候没有执行)。所以这里 this 的指向为window

new 关键词

使用new关键字生成的实例对象,this会指向这个实例对象。如果有返回值对象,则指向返回值

function fn()  
{  
    this.msg = 'haha';  
    // return {};  1. 如果有返回值对象,result.msg 会输出 undefined
    // return null; 2. null的类型为对象,但此时依旧指向实例对象,result.msg 会输出 haha
}
let result = new fn();  
console.log(result.msg); //haha
  • return {}; 1.处 如果有返回值对象,result.msg 会输出 undefined
  • return null; 2.处 null的类型为对象,但此时依旧指向实例对象,result.msg 会输出 haha

显式绑定

call() apply() bind()  都是用来改变函数运行时this指向的(也就是改变函数执行时的上下文),执行后会指向其传入的参数。

想要了解它们,首先需要了解 this 关键字。

优先级

上述的几种方式优先级:new > 显示绑定> 隐式绑定 > 默认绑定

那么当我们想要去改变 this 的指向时,该怎么做呢?

改变 this 的指向

  • 使用 applycallbind
  • 使用 ES6 的箭头函数
  • new 实例化一个对象
  • 使用 _this = this