JS函数调用中this的指向问题详解

JS函数调用中this的指向问题详解


函数调用中的this

在讨论函数调用中的this指向问题之前,我们首先需要知道为什么会有这样的问题,换个说法,也就是说在函数调用的过程当中,this是从哪儿冒出来的。

实际情况是这样的:当函数被调用时,除了声明时规定需要接收的形式参数外,函数还会接收两个参数,分别是thisarguments,因此函数调用方式的不同就会导致this的指向不同。

在js中函数的调用模式有4种:方法调用模式函数调用模式构造器调用模式apply调用模式

下面依次进行讲解。


方法调用模式

当一个函数作为一个对象的属性时,这个函数就被称为方法。

这个方法如果被调用(.方法名()的形式),且方法中使用了this,那么this就被绑定到该对象。看下面的例子:

    let myObject = {
      value: 0,
      increment: function(inc){
        // 当这个 increment 方法被调用时,this 指向的是 myObject 对象
        this.value += typeof inc === 'number'? inc : 1;
      }
    }
    myObject.increment()
    console.log(myObject.value);  // 1
    myObject.increment(2)
    console.log(myObject.value);  // 3

函数调用模式

当一个函数不是一个对象的属性时,那么它就是被当作函数调用的。被当作函数调用的时候,函数中如果使用this, this就会指向全局

感觉上面的话比较抽象?接着上面myObject 的例子,
myObject 添加一个 double 方法:

来分析一下,在 double 方法中,有一个 helper 函数,很明显,helper 函数不是 myObject 的属性,所以它不能被叫做方法。那在这个 helper 函数中用 this, 看看会是什么结果

    myObject.double = function(){
     let helper = function(){
       // 猜猜看,下面的 this 还会指向 myObject 吗? 答案是不会
       // 这里的 this 会指向全局,全局中没有定义过 value, 所以这里的 this.value 的值是 undefined
       console.log('helper中的this.value:'+this.value);  // undefined

       this.value = add(this.value,this.value)

       console.log('此时的this.value:'+this.value); // undefined + undefined = NaN  
     }
     helper()
   }
   myObject.double()
   console.log(myObject.value) // myObjcet.value跟 double的调用毫无干系,值还是 3 

那怎么样才能让内部函数 helper 也能访问到 myObject 中的 this 呢?

由于方法 double方法是能访问到 myObjectthis 的, 因此在double函数中设置一个变量来接收this的值就可以了, 然后内部函数helper通过这个变量就可以访问到 this

   myObject.double = function(){
     let that = this // 解决方法
     let helper = function(){
       that.value = add(that.value,that.value)
     }
     helper()
   }

构造器调用模式

一个函数,如果创建的目的就是希望与 new 结合使用,那么这个函数就被称作构造器函数。

当这个构造器函数前面加上 new 来调用的时候,实际上背地里会创建一个连接到该构造器函数prototype 成员的新对象,同时 this 会绑定到该新对象上。

看个例子就明白了

    let Quo = function(string){
      this.status = string
    }

    Quo.prototype.getStatus = function(){
      return this.status
    }
    
    let myQuo = new Quo('success')
    console.log(myQuo.getStatus())  // 打印 success

apply调用模式

首先需要明确的是:JavaScript是一门函数式编程语言, 所以函数可以调用方法。

当一个函数 (假设是函数A) 调用 apply 方法时, apply 方法会接收两个参数:

  • 第一个参数是要绑定给 this 的值(也就是规定函数A的 this 指向谁)
  • 第二个参数是要传递给函数A 的参数数组
    下面举两个例子来说明 apply 这两个参数的用法:
    let arr = [3,4]
    let sum = add.apply(null,arr) // sum 的值为 7

上面这个例子中, add函数调用 apply 方法, arradd函数接收的参数数组, null 表示没有给 add 函数指定 this。而事实上 add 函数中也没有用到this, 所以也无需指定。

下面再来看一个指定了 this 的例子, 接着上面 Quo 构造函数的例子中的代码:

首先定义一个对象statusObj

    let statusObj = {
      status: 'failed'
    }
    let status = Quo.prototype.getStatus.apply(statusObj) // status的值为 failed

思考一下,为什么?

翻看上面的代码,可以看到 getStatus 函数中, 有 return this.status, 而 apply 接收的参数是 statusObj,也就是将 getStatus 函数中的 this 指向了 statusObj, 所以结果就是 failed


好了,看到这里你应该对函数调用的四种模式,以及四种模式下的this指向问题有了更深的了解了吧! 如果发现了错误之处,还望及时指正哦!
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃面必吃蒜

如果能帮到你,那是最好不过啦!

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值