JS中 this 在各个环境下的指向问题!
一:this在普通函数中的指向 --> window
1 // 普通函数中的this指向 ----> window 2 function fn(){ 3 console.log(this) // ES5 this ----> window 4 console.log(this) // ES6 this----> undefined 5 }
当我们在js脚本中定义一个函数,这个函数当调用时他的指向为window,之所以为window是因为在ES5中定义变量和函数都存在变量提升,所以我们的函数和变量都是挂在 window下,在调用函数时,我们通常都会省略window,直接使用函数,所以调用函数其实是window.fn,所以this的指向为它的上文就是window,那么在ES6中出现了新的特性和规定,将不再存在变量提升,所以在ES6的普通函数中this的指向为undefined。
二:this在回调函数中的指向(不包含事件处理回调函数)- window
1 var obj = { 2 3 a:function(fn){ 4 // 将obj下的 c 方法带入obj下 a 方法中,执行,完成回调 5 fn() 6 }, 7 b:function(){ 8 var arr = [1,2,3,4] 9 arr.forEach(function(){ 10 // 在数组方法 foreach 的回调函数中,this的指向为window 11 console.log(this) // this --> window 12 }) 13 14 // 定时器的回调函数中,this的指向为window 15 setTimeout(function(){ 16 console.log(this) // this --> window 17 },1000) 18 }, 19 c:function(){ 20 // 此回调函数的this为window 21 console.log(this) // this --> window 22 } 23 } 24 // 将obj下的 c 方法带入obj下 a 方法中 25 obj.a(obj.c)
在以上的案例我们可以发现,在回调函数中this的指向都是window,尽管它处在一个对象的环境中,主要原因是回调函数的指向默认为window,且回调函数并没有对象去调用
三:this在事件处理函数中的指向 --> 监听事件对象本身
1 document.addEventListener("click",clickHandler) 2 function clickHandler(){ 3 console.log(this) // this --> document 4 } 5 var obj0={ 6 a:function(){ 7 document.addEventListener("click",this.clickHandler) 8 }, 9 clickHandler:function(){ 10 console.log(this) // this --> document 11 } 12 }
在如上的案例中,分别给document在两个环境下监听click事件,都是指向事件对象本身,事件的this指向是最好辨别的,只需要记住事件对象是谁就可以。
四:对象方法中的this指向 --> 就是调用方法的对象本身
1 var a = 20 2 var obj1 = { 3 a:1, 4 b:this.a, // b:20 - this的指向为 全局的a=20 5 c:function(){ 6 console.log(this) // 这里this的指向为对象 obj1本身 7 } 8 } 9 obj1.c()
在对象中:对象的属性如果使用this,那么this的指向为对象外部的this,对象的方法使用this,调用这个方法的对象就是为this的指向。
五:ES6 类中的this指向 --> 实例化对象
1 class Box{ 2 a = 1 3 static a = 3 4 // 静态属性的this只会去指向相对应的静态属性,不会指向动态方法 5 // 所以c = 3 6 // 当 静态属性 a 没有时,c = undefined 7 static c = this.a // c = 3 8 b = this.a 9 constructor(){ 10 console.log(this) // this --->实例化对象 11 } 12 play(){ 13 console.log(this) // 谁执行 pily方法this就指向谁 14 document.addEventListener("click",this.clickFunction) 15 } 16 clickFunction(e){ 17 console.log(this) 18 } 19 } 20 // 实例化对象 - box 21 var box = new Box()
在ES6 的类中,有两种方法:
一:静态方法:就是在属性或者方法的前面写上 static ,静态方法的this指向为 类本身,不管是属性还是方法
二:动态方法:没有使用 static的都是动态方法,通过构造函数 new出来调用,动态方法的this指向就是谁调用这个方法this指向就是谁,就是实例化对象
六:箭头函数的this指向 -->为箭头函数外部的this
1 var obj3 = { 2 a:()=>{ 3 console.log(this) // this指向 ---> window 4 } 5 } 6 obj3.a() 7 8 var obj4 = { 9 a:function(){ 10 var o = { 11 b:()=>{ 12 console.log(this) // this指向 ---> obj4 13 } 14 } 15 o.b() 16 } 17 } 18 obj4.a()
这个案例中通过2个对象来验证箭头函数改变this的指向,在对象中调用方法那么this指向为该对象,当通过使用箭头函数后,this将当前this的指向全部指向外部,那么obj3.a的this指向本为obj3,遇到箭头函数后,this就指向obj3的外部,为window。同样在obj4也是一样的道理!