JS中this的指向

200 阅读3分钟

前言

this是什么?this指向谁?很多人包括我自己在刚接触到JavaScript中的this关键字时都会有这样两个问题。在经历了一系列的学习之后,我对this也有了一些自己的理解,当然作为初学者,我也并不能十分全面的解析this到底是什么,具体用法有什么,本文我会谈谈我对this的理解,希望对初学者有一定的帮助。

this的定义

什么是this? this是JavaScript保留的的一个关键字,用来引用它所属的对象。当一个函数调用时,会创建一个执行上下文,这个执行上下文包含函数在哪里调用(调用栈),函数的调用方法,传入的参数,this就是用来记录当这个执行上下文信息的一个属性。

this的指向

this的指向取决于this使用的位置

  1. 单独使用时,this指向全局
  2. 在函数中使用,this指向函数调用时,调用栈的位置
  3. 在构造函数中,this指向实例对象
  4. 在定时器,立即执行函数中,this指向全局
  5. 使用call(),apply()方法时,this指向函数所指的对象
  6. 闭包中this默认指向全局

this的绑定规则

1.默认绑定

在不调用其他绑定规则时,就是使用默认绑定,一般是独立函数的调用

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

var a = 2

foo()   // 2

2.隐式绑定

函数的调用通过了某个对象,this就指向这个对象

let obj = {
      name: 'obj',
      foo: function () {
        console.log(this.name);   //this指向obj
      }
    }
    obj.foo()

上面这段代码中,将foo的值设置为一个函数,并使用obj这个对象去调用foo。因此,foo中的this指向obj 打印的结果将会是 “obj"

值得我们注意的是在隐式绑定中,在对象的属性链中,只有最后一层会影响调用的位置,也就是this的指向。如下面的代码:

function foo() {
    console.log(this); // obj5
}
var obj4 = {
    foo: foo,
    obj5: {
        a:1,
        foo: foo
    }
}
obj4.obj5.foo(); 

最后的结果为:obj5

隐式绑定还会出现隐式丢失的现象。

//隐式丢失
function foo() {
     console.log(this.a);
 }

 var obj = {
     a: 2,
     foo: foo
 }

 var bar = obj.foo
 var a = 'glob'

 bar()   //glob     隐式绑定丢失  走默认绑定

上面的代码中,obj.foo引用了foo,而bar通过obj也引用了foo,可以发现,这段代码没有obj也能实现一样的效果,最后bar拿到全局下调用,this指向全局。

隐式丢失还有一种情况就是函数作为参数(回调函数)

function foo(fn){
    var a = 2
    fn()
}

function bar(){
    console.log(this.a);     //  4
}

let obj = {
    a: 3,
    bar: bar
    }
var a = 4
foo(obj.bar)

3.显示绑定

显示绑定就是通过call,apply,bind的方式,call,apply和bind的第一个参数,就是对应函数的this所指向的对象。call和apply都会执行对应的函数,而bind方法不会。

//显式绑定
 function foo() {
    console.log(this.a);
 }
var obj = {
    a: 2,
 }
foo.call(obj)   //  2

new绑定

使用new方法this指向实例化之后的对象

new在干的事情

  1. 创建一个新的对象,并把构造函数中的this指向这个空对象
  2. 对这个对象执行[[原型]]连接
  3. 构造函数的方法,属性被添加到this引用的对象之中
  4. 如果构造函数中没有返回其它对象,返回出来这个对象

箭头函数

箭头函数没有自己的this指向箭头函数的this指向他的父级的this