关于JavaScript中this指向的详解

目录

        提问:什么是this?

一、this的指向

1、全局环境中的this

1.1、全局环境中直接打印this

 1.2、全局环境中调用普通函数

1.3、全局环境中调用定时器和延时器函数

2、 对象中的this

3、构造函数中的this

4、事件中的this

5、 箭头函数中的this

6、 严格模式下的this

二、改变this的指向

1、call 方法

2、apply 方法

3、bind 方法

4、总结


提问:什么是this?

回答:this是Javascript语言中的一个关键字,它代表函数运行时自动生成的一个内部对象,指当前对象,因此this只能在函数内部使用。随着函数执行环境的改变,this所指代的对象也会发生改变,但this始终指向的是调用函数的对象。简单来说就是谁调用了这个函数,this就指向谁(对象)。

一、this的指向

1、全局环境中的this

        所谓全局环境是指在script标签的内部,而全局环境下的作用域就是全局作用域。全局作用域下的this始终指向的是全局对象window。(window是浏览器对象中最顶层的节点)

1.1、全局环境中直接打印this

    <script>
      console.log(this)  //该this指向window
    </script>

 1.2、全局环境中调用普通函数

    <script>
      function fn() {
        console.log(this)  //该this指向window
      }
      fn()
    </script>

1.3、全局环境中调用定时器和延时器函数

    <script>
      setTimeout(function () {
        console.log(this)  //该this指向window
      }, 1000)
      setInterval(function () {
        console.log(this)  //该this指向window
      }, 10000)
    </script>

2、 对象中的this

        对象内部方法的this指向调用这些方法的对象,即由哪个对象调用就指向哪个对象,如果是多层嵌套的情况,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象,而不是window)。

    <script>
      let obj-1 = {
        fn-1: function () {
          console.log(this)
        },
        obj-2: {
          fn-2: function () {
            console.log(this)
          },
        },
      }
      obj-1.fn-1()  //fn-1由obj-1调用,故this指向obj-1
      obj-1.obj-2.fn-2()  //obj-2离的更近,fn-2由obj-2调用,故this指向obj-2
    </script>

3、构造函数中的this

        构造函数中的this与被构造函数实例出来的新对象绑定,即指向该新对象。

    <script>
      let Person = function (name, age) {
        this.name = name  
        this.age = age
        console.log(this)  //该this指向由构造函数 Person实例出来的对象 kun
      }
      let kun = new Person('小黑子', 666)
    </script>

4、事件中的this

        在HTML事件句柄中,this指向的是触发该事件的HTML元素对象,即指向事件源。

    <button id="btn" onclick = "this.style.display='none'">点击删除</button>    
    <script>
      const btn = document.getElementById("btn")
      btn.onclick = function () {
        this.value = "按钮"
        console.log(this)  //给btn注册了on事件,因此该this指向btn
      }
    </script>

5、 箭头函数中的this

        普通函数内部的this指向函数运行时所在的对象,但ES6中新增的箭头函数并没有自己的this对象,所以只能指向上一层作用域(父级作用域)中的this。也就是说,箭头函数内部的this指向是固定的。

    <script>
      var c = 21  //声明同一个全局变量 c 为21
      const obj = {
        c: 42,
        x: () => console.log(this.c),
        k: function () {
          console.log(this.c)
        },
      }
      obj.x()  //箭头函数中的 this指向父级作用域中声明的变量 c,即为21
      obj.k()  //obj调用函数 k,函数 k中的 this指向 obj中声明的变量 c,即为 42
    </script>

6、 严格模式下的this

        JavaScript除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性JavaScript变体的一种方式,即在严格的条件下运行 JS 代码,可消除Javascript语法中的不合理、不严谨之处,减少一些怪异行为,保证代码运行的安全并且可以提高编译器的效率。

        严格模式下全局调用普通函数,其this指向为undefined,其他情况与正常模式相同 

    <script>
      "use strict"
      function fn() {
        console.log(this)  //该this指向undefined
      }
      fn()
    </script>

二、改变this的指向

1、call 方法

function.call( thisArg,arg1, arg2,arg3······ )//立即执行函数

function: 需要改变this指向的原函数
thisArg: 改变后的this所指向的新目标对象

arg:需要修改的参数

    <script>
      function fn(name, age) {
        this.name = name
        this.age = age
        console.log(this)
      }
      const obj = {}
      fn.call(obj, "小黑子", 666) //函数fn中的this指向空对象obj并具备name和age属性
    </script>

2、apply 方法

function.apply( thisArg,[arg1, arg2,arg3······] )//立即执行函数

function: 需要改变this指向的原函数
thisArg: 改变后的this所指向的新目标对象

[arg]:一个数组,包含需要修改的参数

    <script>
      function fn(name, age) {
        this.name = name
        this.age = age
        console.log(this)
      }
      const obj = {}
      fn.apply(obj, ["小黑子",666]) //函数fn中的this指向空对象obj并具备name和age属性
    </script>

3、bind 方法

function.bind( thisArg,arg1, arg2,arg3······ )//不会立即执行函数

function: 需要改变this指向的原函数
thisArg: 改变后的this所指向的新目标对象

arg:需要修改的参数

该方法并不会调用函数,仅仅是改变this指向,相当于返回一份修改了this的函数的拷贝

    <script>
      function fn(name, age) {
        this.name = name
        this.age = age
        console.log(this)
      }
      const obj = {}
      //函数被借用时,不会立即执行,而是返回一个新的函数
      //所以需要自己手动调用新的函数来改变this指向
      const newFn = fn.bind(obj, '小黑子', 666) //this指向空对象obj并具备name和age属性
      newFn()
    </script>

4、总结

方法区别
call既可以调用函数又可以传参数,参数只需用逗号隔开
apply既可以调用函数又可以传参数,参数需要用一个数组进行包裹
bind不可以调用函数,可以传参数,参数只需用逗号隔开,返回得到一个新的函数,执行需要再次调用
  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值