Javascript中的this(一)

165 阅读4分钟

学过Javascript的同学一定被this搞得头晕脑胀过,我自己也困惑了好久,一下指向全局,一下指向对象,一下又指向undefined,如果不了解this的特性以及绑定规则的话,你之后学Javascript只会越来越困惑,这里我特意去整理了一下比较全面的this特性以及绑定规则,希望能帮助到你。

为什么需要this

   const obj = {
     name: 'zengge',
     age: 22,
     eating(){
       console.log(`${this.name}在吃东西`) 
     },
     running(){
       console.log(`${this.age}${this.name}在吃东西`) 
     },
   }

上图的代码this.namethis.age能不能用直接用obj代替呢?答案是可以的。这样看来从某些角度上来说,开发中并不需要用到this,完全可以直接用当前的对象代替this啊,那为什么还要用this呢?好的,那么如果说这个对象里有1000个方法,每个方法都用到了对象中的属性,有一天我们需要改变这个对象的名字,那么我们要一个一个去修改这1000个方法中的obj属性名吗?所以没有this是可以的,但是有了this可以大大增加开发和维护的效率,这就是thisJavascript中存在的意义。

全局作用域中的this

在大多数情况下,this都是出现在对象或者函数中,但是在浏览器或者全局中this指向的就是window对象。 截屏2022-04-21 20.08.03.png
而在node中,this指向的是一个空对象。 截屏2022-04-21 20.14.36.png
我们开发中很少会在全局下去使用this,一般都是在函数或者对象中使用。那么如果在函数中使用了this,它的绑定规则又是什么呢?

    function foo() {
      console.log(this)
    }
    foo()
    const obj = {
      foo,
    }
    obj.foo()
    foo.apply('123')

这三个函数调用分别打印什么?结果会是一样吗? 截屏2022-04-21 20.28.28.png
显然,结果并不一样。由此可知,函数中的this指向跟函数所处的位置无关,而是跟函数被调用的方式有关。第一个foo函数被调用是在全局中被调用,所以this指向的是全局window。第二个函数存在于obj对象中而且被obj对象调用,所以this指向obj对象本身。第三个函数经过了apply函数调用,改变了this原本的指向,从而指向了内置的String类。事实上,this的绑定总共有四种,只要掌握了这四种绑定规则,就真正掌握住this的使用。

四种this绑定规则

  • 默认绑定
  • 隐式绑定
  • 显式绑定
  • new绑定
默认绑定

什么情况下是默认绑定呢?就是当一个函数独立调用时,也就是说可以理解成函数没有被绑定到某个对象中进行调用,此时的this就会绑定到当前全局作用域(不一定是window)。

案例一
    function foo() {
      console.log(this)
    }
    function foo2() {
      console.log(this)
      foo()
    }
    function foo3() {
      console.log(this)
      foo2()
    }
    foo3()

想想这三个this分别打印什么,没错,就是你想的那样,三个都是打印window对象。 截屏2022-04-21 21.32.49.png
如果你觉得简单我们来看看下面的案例:

案例二
   const obj = {
     name: 'zengge',
     foo(){
       console.log(this)
     }
   }
   const objFunc = obj.foo
   objFunc()

这个案例我估计会有不少同学会掉陷阱了。你会说哎这个不是上面说过的么,你看foo函数在obj对象里,那执行这个foo函数里面的this不是指向obj对象本身吗?如果这样想那你就掉坑喽。我们上面说过this在函数中的指向跟函数的位置无关,而跟函数的调用方式有关。我们这里的objFunc指向的是foo函数没错,但是objFunc函数是独立调用的,并没有说是通过某个对象以点的方式调用的。所以说符合默认绑定规则,函数中的this指向全局,而这里的全局就是指向window对象。

隐式绑定

隐式绑定指的是被绑定到某个对象中的函数通过对象点的方式调用,此时的this就会隐式地绑定到该对象上。我们还是拿之前的代码举例:

案例一
   function foo() { 
     console.log(this)
   }
   const obj = {
     foo,
   }
   obj.foo()

截屏2022-04-21 21.49.23.png 这里为什么打印的是foo对象呢?注意这里的foo函数是被obj.的方式调用的,这个时候js引擎就会将foo函数中的this绑定到foo对象了。

案例二
   const obj1 = {
     name: 'zengge',
     foo(){
       console.log(this)
     }
   }
   const obj2 = {
     name: 'zengge2',
     bar:obj1.foo
   }
   obj2.bar()

那么这里的obj2.bar函数执行打印的又是什么呢?是obj1对象吗?还是window对象呢?都不是,结果是obj2对象。 截屏2022-04-21 22.02.07.png
这应该很好理解了,上面说了隐式绑定的规则了,bar函数在此处并不是独立调用,而是通过obj2.的方式调用,所以this隐式地被绑定给了obj2对象。
好了今天就先总结两种绑定规则,明天总结后面两种,记得好好阅读文章哦。