JavaScript 中允许指定(改变)函数中 this 的指向,有 3 个方法可以动态指定普通函数中 this 的指向

一、call()

call的作用:使用 call 方法调用函数,同时指定被调用函数中 this 的指向

call的应用场景: Object.prototype.toString.call(数据)  检测数据类型

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>改变this指向-call</title>
</head>

<body>
  <script>
    // 1. 改变this指向 - call 
    const obj = { name: '佩奇' }

    // call() 作用: 第一个调用函数  第二改变this指向
    function fun(x, y) {
      console.log(this)
      // console.log(x + y)
      return x + y
    }
    fun()  // this 指向window
    // fun.call(obj)  //  this 指向 obj 对象
    // fun.call(obj, 1, 2)  //  this 指向 obj 对象
    console.log(fun.call(obj, 1, 2))  // 返回值就是函数 返回值

    // 2. call的应用场景 - 检测数据类型
    // 2.1 typeof 检测数据类型不够精确的
    console.log(typeof '123') // string
    console.log(typeof []) // object
    console.log(typeof null) // object

    // 2.2 Object.prototype.toString()  返回的结果是[object xxx类型]
    // console.log(Object.prototype.toString('123')) //  [object Object]
    console.log(Object.prototype.toString.call('123'))  // [object String]
    console.log(Object.prototype.toString.call(123))  // [object Number]
    console.log(Object.prototype.toString.call([]))  // [object Array]
    console.log(Object.prototype.toString.call(null))  // [object Null]
  </script>
</body>

</html>

二、apply()

apply()的作用:使用 apply 方法调用函数,同时指定被调用函数中 this 的值

apply()的使用场景:apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值

call和apply的区别是?

都是调用函数,都能改变this指向 参数不一样,call是传递参数列表,apply传递的必须是数组

call可以用来检测数据类型,apply可以求数组最大值

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>改变this指向apply</title>
</head>

<body>
  <script>
    // 改变this指向apply 
    // 1. 基本使用
    const obj = { name: '佩奇' }
    function fun(x, y) {
      console.log(this)
      console.log(x + y)
    }
    fun()
    // fun.apply()  // 1. 作用1调用函数
    // fun.apply(obj)  // 2. 作用2 改变this指向 obj
    fun.apply(obj, [1, 2])  // 参数必须是数组

    // 2. 使用场景- 求数组的最大值/最小值
    console.log(Math.max(...[1, 2, 3]))  // 3

    // apply 或者 call 如果不需要改变this指向 写 null 
    console.log(Math.max.apply(null, [8, 2, 3]))  // 8
    console.log(Math.min.apply(null, [8, 2, 3]))  // 2

  </script>
</body>

</html>

效果展示:

三、bind()

bind() 方法不会调用函数。但是能改变函数内部 this 指向 

返回由指定的 this 值和初始化参数改造的 原函数拷贝 (新函数)

使用场景: 当我们只是想改变 this 指向,并且不想调用这个函数时,可以使用 bind,比如改变定时器内部的this指向.

代码分享:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>改变this指向-bind方法</title>
</head>

<body>
  <button class="code">发送验证码</button>
  <script>
    const obj = { name: '佩奇' }
    //改变this指向-bind方法
    // 1. 基本使用
    function fun(x, y, z) {
      console.log(this)
      console.log(x + y + z)
    }
    // fun()
    // fun.bind()  // bind不会调用函数
    // const fn = fun.bind()  // 返回的是对原来函数的拷贝
    // console.log(fn)
    // console.log(fn === fun)  // false

    // const fn = fun.bind(obj)  // bind 可以改变this指向
    const fn = fun.bind(obj, 1, 2, 3)  // 


    fn()  // 调用函数


    // 2. 使用场景 - 不需要调用函数,但是又想改变函数内部的this指向

    // 1. 发送短信5秒倒计时业务
    const codeBtn = document.querySelector('.code')
    let flag = true  // 开关变量,用来防止多次点击
    codeBtn.addEventListener('click', function () {
      if (flag) {
        // 1.2 利用定时器做倒计时效果 setInterval 
        let i = 5
        // 点击之后立马变化文字
        this.innerHTML = `05秒后重新获取`
        // 定时器
        let timerId = setInterval(function () {
          i--
          this.innerHTML = `0${i}秒后重新获取`

          // 1.3 时间到了 就显示文字为 重新获取
          if (i === 0) {
            this.innerHTML = `重新获取`
            // 停止定时器
            clearInterval(timerId)
            flag = true
          }
        }.bind(this), 1000)
        // 关闭开关 
        flag = false
      }
    })
  </script>
</body>

</html>

三种方法的总结:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>this指向总结</title>
</head>

<body>
  <button>点击</button>
  <script>
    // this指向总结
    // 1. 普通函数
    // 1.1 全局内调用
    function fn() {
      console.log(this)  // window
    }
    fn()

    // 1.2 对象内调用
    const obj = {
      name: '佩奇',
      sayHi() {
        console.log(this) // obj
      }
    }
    obj.sayHi()

    // 1.3 构造函数内this
    function Person() {
      this.name = name
      console.log(this)
    }
    const zs = new Person()

    // 1.4 事件处理函数中的this
    document.querySelector('button').addEventListener('click', function () {
      console.log(this)
    })

    // 1.5 特殊调用 call  apply  bind 可以改变this指向
    const o = { name: '佩奇' }
    function fun() {
      console.log(this)
    }
    fun.call(o)


    // 2. 箭头函数 没有this,是沿用上一级作用域的this 


  </script>
</body>

</html>

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐