最近碰到了一个问题，环境是vue2、ts、vue-class-component，写一个方法时发现声明的变量虽可以访问到但没有响应式，随后发现方法中的this不是VueComponent，在检查为什么this指向有问题时发现新写的方法用的是箭头函数，改成普通函数后就正常了，对于这块有点疑惑，因此整理记录关于this指向的情况。1.不同情况下this的指向方法/函数调用中的thiswindow.name = 'win' function fun () { console.log(this.name) } let obj1 = { name: 'jack', fun } let obj2 = { name: 'bob', } obj2.fun = obj1.fun fun() // win obj1.fun() // jack obj2.fun() // bob如上代码，直接执行fun函数，打印“win”，表明此时函数中的this指向的对象是window。而使用obj1.fun()调用fun函数，打印“jack”，此时this指向的对象是obj1。obj2.fun()的执行结果为“bob”，表明obj2对象的fun函数虽然是由obj1的fun函数赋值得到，但由于是obj2对象调用的，所以this指向obj2，打印了obj2的name属性。window.name = 'win' let fun = () => { console.log(this.name) } let obj = { name: 'jack', funA } obj.fun() // win如上代码，当fun函数为箭头函数时，因为定义funB时所在的作用域是在全局作用域window下，所以funB内的this是window，因此obj.fun()的打印结果是”win“而非”jack“。事件回调中的this行内绑定 直接将函数执行语句"handleClick()"作为属性绑定到dom标签上，当click事件触发时，语句可视为是在全局作用域下执行的，因此this指向window。 当回调函数是箭头函数时，函数内this也为window。js动态绑定 通过js赋值函数给dom对象的onclick属性的方式绑定回调函数，回调函数是被dom对象所调用的，因此this指向dom对象。 当绑定的回调函数是箭头函数时，函数内this指向window。事件监听 通过事件监听方法绑定的回调函数，this同样指向了dom对象。 当绑定的回调函数是箭头函数时，函数内this指向window。构造函数中的thisfunction Obj() { console.log(this) } let o = new Obj() // Obj {} console.log(this) // Window {}如上代码第五行执行new Obj()语句时，打印了“Obj {}”，这是因为在new关键字会首先创建一个空对象，并将控对象的隐式原型指向构造函数的显式原型，最后将构造函数中的this指向了这个新创建的对象，因此在构造函数中，this会指向一个新创建的对象，同时它也是new语句的返回值。另外箭头函数由于没有自己的this，是不可以作为构造函数的。call、apply、bindcall、apply和bind是js中三个很神奇的函数，使用它们可以改变函数体内部this的指向。let func = function() { console.log(this.name, [...arguments].join(',')) } let obj1 = { name: 'obj1', func } let obj2 = { name: 'obj2', } obj1.func(0) // obj1 0 obj1.func.call(obj2, 1, 2, 3) // obj2 1,2,3 obj1.func.apply(obj2, [4, 5, 6]) // obj2 4,5,6如上代码，call和apply方法都可以改变函数内部this的指向，区别在于call方法第一个参数是所要改变的this（上下文），其它参数是func函数的参数，apply方法的第二个参数是fun函数参数的数组。let func = function() { console.log(this.name, [...arguments].join(',')) } let obj1 = { name: 'obj1', func } let obj2 = { name: 'obj2', } let newFunc = obj1.func.bind(obj2) newFunc(1, 2, 3) // obj2 1,2,3bind方法可以返回一个新的函数，这个新函数的this为bind的参数，这样无论新函数在哪里被调用，其内部的this都是不会变的。class中this的指向class Person { constructor(name){ this.name = name } getName() { console.log(this.name) } } let p = new Person("tom") p.getName() // tomclass中所定义的普通函数会被添加到类的原型上，调用方法时，调用方是类的实例对象，因此方法中的this指向类的实例对象。class Person { constructor(name){ this.name = name } getName = () => { console.log(this.name) } } let p = new Person("tom") p.getName() // tomclass中所定义的箭头函数会在constructor中自动添加到类的实例对象上，调用方法时，箭头函数的this也是指向类的实例对象的。箭头函数箭头函数体内的this对象，是定义该函数时所在的作用域所指向的对象，而不是使用时所在作用域指向的对象。window.name = 'win' let funA = function() { console.log(this.name) } let funB = () => { console.log(this.name) } let obj1 = { name: 'jack', funA } let obj2 = { name: 'bob', funB } obj1.funA() // jack obj2.funB() // win如上代码，obj2.funA()和obj2.funB()打印结果分别是“jack”和“win”，说明箭头函数funB内的this取的是window，因为定义funB时所在的作用域是在全局作用域下，所以funB内的this是window。2.问题分析将开篇所提到的问题进行简化： 如上的Vue代码中，在组件成功挂载后的created回调函数中，分别调用了普通函数click和箭头函数click1打印this和this.name，他们所打印出来的this.name是一样的，但普通函数中的this是Vue组件的实例对象，而箭头函数中的this是basicInfoTab类的实例对象。按照上面class中this的指向所述的那样，普通函数和箭头函数中的this应该是一样的才对。要搞清楚原因就需要去探究basicInfoTab类成为组件类，以及实例化组件类的过程，通过查询资料了解到大概有以下步骤：实例化类：Vue使用“new”关键字和类的构造函数创建类的新实例。初始化组件：Vue初始化新创建的类实例，设置其数据（data）、计算属性（computed）、方法（methods）等。创建组件实例：Vue将初始化后的类实例转化为Vue组件实例。在这个过程中，Vue会添加一些特殊的属性和方法，例如生命周期钩子（如created、mounted等）。挂载组件：最后，Vue将组件实例挂载到DOM元素上。在这个过程中，Vue会创建一个新的Vue实例，并将模板编译成虚拟DOM，然后将虚拟DOM渲染成真实DOM，并插入到挂载的元素中。由上可知，VueComponent组件实例对象是在basicInfoTab类实例对象的基础上初始化的，click是普通函数，因此他的this是VueComponent组件实例对象，由于click1是箭头函数，所以click1内部this会一直指向basicInfoTab类的实例对象。即使是VueComponent组件实例对象调用了click1，其内部this仍然还是指向basicInfoTab类实例对象。将此情况换成一个更简单的例子：class Person { a() { console.log(this) } b = () => { console.log(this) } } let p = new Person() class Dog { a = p.a b = p.b } let d = new Dog() d.a() // Dog {...} d.b() // Person {...}上面代码中，Dog类中的属性a和b都是从Person类的实例对象p赋值而来的，Dog类的实例对象d分别调用a方法和b方法，作为普通函数的a方法中this指向自身，而箭头函数根据其定义依然指向着Person类实例对象p。因此可以对开篇遇到的问题进行解释，因为箭头函数中的this是basicInfoTab类的实例对象，所读取到的属性没有经过Vue的处理，所以不具备响应式。3.总结方法调用模式下，this总是指向调用的对象，this的指向与所在方法的调用位置有关，而与方法的声明位置无关（箭头函数例外）；在事件回调中，行内绑定的事件不论是普通函数还是箭头函数，它们的this都指向window；动态绑定及事件监听方式绑定的普通函数，this指向dom对象，绑定的箭头函数则指向window；构造函数调用模式下，this指向被构造的对象；apply、call、bind 调用模式下，this 指向函数的第一个参数；class中，不论是普通函数还是箭头函数内的this都指向实例对象；箭头函数体内的this和实际调用函数的对象无关，是定义该函数时所在的作用域所指向的对象，而不是使用时所在作用域指向的对象。参考内容：https://zhuanlan.zhihu.com/p/42145138https://juejin.cn/post/6973654160872833038https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this#%E5%B0%9D%E8%AF%95%E4%B8%80%E4%B8%8Bhttps://juejin.cn/post/6981251280236707853#heading-3https://juejin.cn/post/7035257186565488670https://juejin.cn/post/6954692013489029151#heading-7https://juejin.cn/post/6930896449878097927#heading-14https://www.zhihu.com/tardis/zm/art/57204184?source_id=1003https://blog.csdn.net/yiyueqinghui/article/details/106792408https://juejin.cn/post/6844903906917482503