上下文(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对象调用的,所以问题就迎刃而解啦
未完待续...
前端远比想象中的还要复杂,需要学习的还有很多,脚踏实地记录好遇到的麻烦与经验,三省吾身,才能慢慢积累经验。