🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 普通函数在不同的执行环境下,this指向 this是什么,是和执行上下文绑定的,也就是说每个执行上下文中都有一个 this。 ### 1、在全局中,指向window ``` js // 普通函数 function fn(){ console.log(this) } fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} ``` ``` js // 箭头函数 var fn = ()=>{ console.log(this) } fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} ``` 在全局中,指向就没有什么可说的,都是window对象 ### 2、普通对象下的函数,不同的执行环境 #### 2.1当普通函数被普通对象的属性(方法)调用 ``` js // 普通函数 var obj = { a: 123, fn: function(){ console.log(this) } } var obj2 = obj.fn obj2() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} obj.fn() // {a: 123, fn: ƒ} ``` ``` js // 箭头函数 var obj = { a: 123, fn: () => { console.log(this) } } var obj2 = obj.fn obj2() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} obj.fn() // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} ``` 当普通函数被普通对象的属性(方法)调用,则this执行这个普通对象obj; 当箭头函数被普通对象的属性(方法)调用,则this指向window对象。 #### 2.2 注意高阶函数,先后执行的环境有所变化时,this执行跟随变化 注:可通过abc进行改变指向(apply、bind、call) ``` var a = 'window' var obj = { a: 123, fn:function(){ console.log('fn的this:',this,this.a) return function(){ console.log('匿名:',this,this.a) } }, cn:function (){ return ()=>{ console.log('匿名箭头:',this,this.a) } } } var obj_fn = obj.fn var obj_cn = obj.cn obj_fn()() // 结果如下图 obj_cn()() obj.fn()() obj.cn()() ``` ![](https://img.kancloud.cn/9b/77/9b77184655a529708589b338938f65e3_921x190.png) #### 2.3定义_that指向fn的this ``` // 普通函数 var a = 'window' var obj = { a: 123, fn:function(){ var _that = this console.log('fn的this:',this,',this.a:',this.a) return function(){ console.log('匿名:',',this: ',this,',_that: ',_that) } } } var obj2 = obj.fn obj2()() obj.fn()() ``` ![](https://img.kancloud.cn/c8/c9/c8c9840af084048c1e84d834a9df6e0f_1529x124.png) ``` js // 箭头函数 var a = 'window' var obj = { a: 123, fn:function(){ var _that = this console.log('fn的this:',this,',this.a:',this.a) return ()=>{ console.log('匿名:',',this: ',this,',_that: ',_that) } } } var obj2 = obj.fn obj2()() obj.fn()() // _that在这里最容易犯错了 ``` ![](https://img.kancloud.cn/47/4c/474cb0eee1b8ac69f532c92119b69871_1525x119.png) #### 2.4全局变量累计 ```js var a = 1; window.b = 2 var obj = { a: 2, b: 4, ab:function(){ // 此处换成箭头函数,会怎么样呢? this.a+=5; a+=8 this.b+=5 b+=8 console.log(a,b,this.a,this.b,'a-----b') } } obj.ab(); // 9 10 7 9 "a-----b" console.log('ab:',a,b,this.a,this.b) // ab: 9 10 9 10 var fn = obj.ab; fn() // 22 23 22 23 "a-----b" console.log('ab-fn:',a,b,this.a,this.b) // ab-fn: 22 23 22 23 ``` 分析: 1、`obj.ab(); `时,a和this.a区别就是一个全局window.a(既var a),一个普通对象obj.a(this.a); 2、`console.log('ab:',a,b,this.a,this.b) `时,可通过window===this、window.a=a理解,故都是a===this.a理解,记住此时a=9、b=10; 3、`var fn = obj.ab;fn() `时,*fn执行环境时window*,那此时this.a等于什么呢?又等于什么呢?可以这样理解window.a=this.a=a,故a=9+5+8,b=10+5+8 ab函数换成箭头函数,则函数内:`var a = window.a=this.a`了。 #### 2.5内层函数不会继承上层函数this ``` var obj = { ab:function(){ console.log('ab:',this) function fn(){ console.log('fn:',this) } fn() } } obj.ab() // 结果图下 fn 不会继承ab()的this var out = obj.ab out() ``` ![](https://img.kancloud.cn/66/61/6661b076c6b688e7c1da38a9a9f9b5d1_682x122.png) ### 总结: 普通函数this指向,取决于调用时的环境在哪里; 箭头函数this指向,取决于父级上下文环境在哪里; 注:箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。