- A+
所属分类:Web前端
1、首先
- 首先要解释下,函数体内变量的作用域是在函数定义的时候就确定的,而不是运行时;
- 函数的上下文是在调用时确定的,函数体内的this指向其上下文;
- 箭头函数没有自己的this,它的this指向的是它上级的this,而它上级的this指向的是上级的上下文。
2、普通函数的this,指向其调用者,箭头函数this,指向其上级this
let app = { a: 1, fn: function () { console.log('app.fn:', this, this.a); // this指向需要函数被调用时才能确定,当app.fn()执行, // 确定其上下文为app,所以this指向app对象 // this.a = app.a = 1 } } window.a = 0 let app2 = { a: 2, fn: () => { console.log('app2.fn:', this, this.a); // app2.fn()执行,上下文为app2,this本应指向app2对象, // 但是fn是箭头函数,所以this指向它上级的this,也就是 // 指向app2的this,由于app2的this指向的是其上下文,所以这里就是window, // this.a = window.a = 0 } }
拓展:var、let和const声明的数据,作用域不同,var声明的对象可以在global全局作用域下查找,也就是赋值给了window对象;而let和const声明的对象只能在script作用域下查找,所以window对象上不会显示声明的app等对象和函数。var声明的对象和function函数都可以在global全局作用域下找到。
说到了script,多个script在浏览器中一般是分块编译的,不是同时编译。但是作用域只有一个,就是script作用域。
3、seiTimeout中的this,指向window,箭头函数this,指向其上级this
let app3 = { a: 3, fn: function () { setTimeout(() => { console.log('app3.fn:', this, this.a); // app3.fn()执行,但输出语句在setTimeout中, // this本应指向window,但箭头函数的this指向其上级的this, // 所以this指向fn的this,也就是fn的上下文,this指向app3对象 // this.a = app3.a = 3 }, 1000); } } let app4 = { a: 4, fn: ()=> { setTimeout(() => { console.log('app4.fn:', this, this.a); // app4.fn()执行,this本应指向window, // 但箭头函数的this指向fn的this,fn的this指向app4的this, // app4的this指向app4的上下文 // 所以this指向app4的上下文,this指向window // this.a = window.a = 0 }, 1000); } } let app5 = { a:5, fn:function(){ setTimeout(() => { console.log('app5.fn:', this, this.a); // app5.fn()执行,this指向fn的this, // fn的this指向fn的上下文,也就是this指向app5 // this.a = app5.a = 5 }, 1000); } }
4、数组中的函数,调用后的this,指向该数组
function app6() { console.log('app6.fn:', this, this.a); } let arr = [0, 1, 2, app6] arr[3]() // 函数执行,上下文是arr数组,this指向arr, // this.a = undefined, this[0] = 0