上下文(this)的初步理解

先简单总结一下

首先上下文(context)= this

1.如果你想输出this,那么你就要找输出this的函数被调用时,是谁调用

ps:记住,普通函数只有被调用的时候,我们才能判断this是谁的

如果用call,apply,bind改变了this,那么就要去他们的第一个参数就是this的指向

const a = {
  b: 1,
  c: function() {
    console.log(this)
  }
}

const xx = {}

a.c() // 等同于 a.c.call(a) 此时上下文便是函数c所在的作用域a,输出对象a
a.c.call(xx) // 此时上下文便是函数c所在的作用域xx,输出对象xx

2.如果使用了箭头函数,那么就得看声明(定义)了这个箭头函数,箭头函数的this就是声明它的对象的this

const a = {
  b: 1,
  c: () => {
    console.log(this)
  }
}

const xx = {}


a.c() // 因为是a调用的,所以要找a的this,a的this就是window
a.c.call(xx) // 虽然call改变了this的指向,但因为c是箭头函数,所以还是会找xx的this,也就还是window

3.如果是setTimeout的第一个参数,那么this会被改写指向window

const a = {
  b: 1,
  c: function() {
    setTimeout(function() {
      console.log(this) // window.setTimout,所以指向是window
    }, 0)
  },
  d: () => {
    setTimeout(function() {
      console.log(this) // window.setTimout,所以指向是window
    }, 0)
  }
}

a.c()
a.d()

但如果setTimeout里面用箭头函数,那情况又不同了,因为箭头函数会指向声明箭头函数的对象的this

const a = {
  b: 1,
  c: function(){
    setTimeout(() => {
      console.log(this) 
    }, 0)
  },
  d: () => {
    setTimeout(() => {
      console.log(this) 
    }, 0)
  }
}

a.c() // c声明了,c的this指向a
a.d() // d声明了,但是d也是箭头函数,d的this指向a的this,也就是windows

4.最后再拓展一下,因为call,bind,apply会改变this的指向,但是我们只要找好这个函数本身的指向(比如下面的a的),再把本身指向替换成改变的指向(a改成xx)就行了

const a = {
  b: 1,
  c: function(){
    setTimeout(() => {
      console.log(this) 
    }, 0)
  },
  d: () => {
    setTimeout(() => {
      console.log(this) 
    }, 0)
  }
}

const xx = {}


a.c.call(xx) // c声明了,c的this指向a, 又被call改成xx,所以最后是输出xx
a.d.call(xx) // d声明了,但是d也是箭头函数,d的this指向a的this,但是又被call改成xx的this 也就是window,最后还是window

 5.再出一道巩固一下

const a = {
  b: 1,
  c: function(){
    console.log('c-this', this) // 最后是a.c(),即a.c.call(a),所以this是a
    function test() {
      console.log('c-test-this', this) // 指向调用test()的对象,由下文test.call()的第一个参数是空可得,输出window
      setTimeout(() => {
        console.log('c-in-this', this) // 指向声明这个箭头函数的对象的this,虽然看起来好像是c或者a,但其实是window声明了test(),因为test()并不是c或者a的方法,所以最后是window
      }, 0)
    }
    test() // test.call()时,并没有绑定第一个参数,所以第一个参数是空即window
  },
  d: () => {
    setTimeout(() => {
      console.log(this) 
    }, 0)
  }
}

a.c() 
a.d() // d声明了setTimeout()的箭头函数,照理说this应该指向d的this,但是d也是箭头函数,d的this指向a的this,所以最后 箭头this => d的this => a 的this => window

明显,这里的坑是test(),但我们只要记住普通函数只有被调用的时候,我们才能判断this是谁的,

就知道test()实际是window对象调用的,所以问题就迎刃而解啦

 

未完待续...

posted @ 2021-03-22 23:23  re-saika  阅读(223)  评论(0编辑  收藏  举报