# JS-This(一)

🐴

# 前言

今天来写一写JavaScript中的this,虽然this已经被讨论烂了,但是我们这里还是从两个角度去探索一下,这篇文章我们从多种情况来总结出this的指向,下一篇关于this的文章中我们从另一个角度来探讨一下this的指向问题。这篇文章只是总结了常见的this指向的问题,并没有从根源说起,如果想了解更多,可以看第二篇关于this的文章

this其实就是执行上下文的一个属性,在javaScriptthis时在进入上下文时确定的,并且在上下文运行期间一直不会发生变化。下面我们来看看this指向的多种情况。

# 全局中的this

全局中的this对于我们来说应该还是很好理解的,全局中的this, 指向的就是 window

console.log(this)  // 指向window

var a = 10;
console.log(this.a) // 10  this执行window

# 函数中的this

函数中的this相对于全局中的this来说比较难搞,我们需要考虑函数的执行上下文,因为this是在函数调用时来确定的,也就是说调用函数的方式不同会影响this的指向,下面我们来看看函数中的this,

// 全局中执行fun函数
function fun(){
  console.log(this) 
}
fun() // this 指向window

// 以原型的构造函数方式调用
fun.propotype.constructor() // this 指向fun.propotype对象

//对象中调用fun

var obj = {
  fun:function(){
    console.log(this)  
  }
}
obj.fun() // this 指向 obj对象
var f = obj.fun;
f()// this 指向 window对象

我们可以发现,函数作为对象的方法调用时,会指向调用该函数的对象(这么说不是很严谨,我们讨论的只是this的指向情况), 如果将对象的方法赋值给全局变量,那么在函数执行时,this会指向window

另外我们看看下面这种情况:

 var obj = {
    bar: function () {
        console.log(this);
    },
    fun:function(){
        function f(){
            console.log(this)
        }
        f()
    }
};
(obj.bar)(); // this 指向obj
(true&&obj.bar)(); // this 指向window
(obj.bar = obj.bar)(); // this 指向window
obj.fun();  // this 指向window

为了方便记忆我们可以这样确定this,首先括号()是组运算对this的确定没有影响,但是其他的赋值运算会对this造成影响,比如=&&||, 此时会将this值会是undefined,并最终指向window。所以针对上面的例子我们就可以得出

  1. (obj.bar)() 结果为this 指向obj, 因为组运算对this的确定没有影响;
  2. (true&&obj.bar)()(obj.bar = obj.bar)()的结果为this指向window,因为赋值运算会改变this指向;
  3. obj.fun()结果为this指向window,这种情况下,我们可以记住,函数执行后,内部函数执行时this的值会是undefined,并最终将会指向window,(虽然这么去理解是不正确的,但是为了更快的记住this的指向,只能这么干了。)

# 定时器中的this

setTimeout方法和setInterval方法是全局对象window的两个方法,在这两个方法触发的函数(不包含ES6箭头函数)中的this指向window

 var foo = {
    bar: function () {
        setTimeout(function(){
            console.log(this)
        },2000)
    },
    fun:function(){
        setInterval(function(){
            console.log(this)
        },2000)
    },
};

foo.bar()  // this 指向 window
foo.fun()  // this 指向 window

# DOM事件中的this

DOM事件中绑定的函数中的this指向触发该事件的DOM元素。

<div id="test">
   aaaaaaaaaaaaaae
</div>
<script>
  var div = document.querySelector("#test")
  div.onclick = function(){
      console.log(this)  // 指向id为test的元素
  }
</script>

# ES6 中的this

es6中讨论this 我们这里就不得不提箭头函数了, 和es5中,函数在执行时确定this不同,es6的箭头函数中根本没有自己的this,箭头函数中是继承自上级上下文中的this

var foo = {
    bar: function () {
        setTimeout(function(){
            console.log(this)
        },2000)
    },
    fun:function(){
        setTimeout(()=>{
            console.log(this)
        },2000)
    },
};

foo.bar()  // this 指向 window
foo.fun()  // this 指向 foo
var newF = foo.fun;
newF() // this 指向 window

通过上面例子我们可以看到,定时器setTimeout触发函数中的this应该是指向window的,但是当在setTimeout中使用箭头函数时,因为箭头函数没有this,它的this是继承上级的上下文中的this的。

第二种情况我们可以看出,在执行foo.fun()时箭头函数中的this就是继承自foo.fun中的this, 当通过foo.fun()调用函数时,foo.fun中的this指向foo,所以箭头函数中的this指向foo对象

第三种情况通过newF()调用函数时,foo.fun中的this指向undefined,最终指向window上面我们也分析过,所以箭头函数中的this指向window

所以在确定箭头函数中的this时,我们只需要确定它上级的上下文中的this即可。

我们在来看看下面在DOM事件中箭头函数内的this

<div id="test">
   aaaaaaaaaaaaaae
</div>
<script>
  var div = document.querySelector("#test")
  div.onclick = () =>{
      console.log(this)  // 指向 window
  }
</script>

DOM事件中箭头函数内的this也不再指向触发事件的元素了,而是指向它的上级上下文中的thiswindow

# 构造函数中的this

在构造函数中this还是很好确定的,在构造函数中this永远指向通过构造函数创建的对象。

function people(){
  this.name = "king";
  this.age = 52
}

var one = new People()
var two = new People()

上面在构造函数中的this会指向通过new创建出来的对象。第一种情况下people中的this指向 one对象,第二种情况下people中的this指向 two对象

最近更新时间: 7/2/2021, 11:27:27 AM