javascript this指向和改变this指向的call、apply、bind三个方法

this指向

1、全局作用域下 window

console.log(this)   //window

2、普通函数 window

function fn() {
    console.log(this)   //window
}
fn()

3、立即执行函数IIFE window

   // IIFE(立即执行函数)->window (其实就相当于被调用的普通函数)
    (function () { console.log(this) })()  // window
    (function () { console.log(this) }())  // window

4、严格模式,全局作用域中的 this 指向 undefined

 function fn() {
        'use strict'
        console.log(this)  // 函数内部开启严格模式, this指向undefined
      }
fn()

5、对象中的方法中的this谁调用指向谁(指向调用它的这个对象)

let obj = {
    name: '张三',
    speak: function () {
       console.log(this)
    }
}
obj.speak()   // obj

6、注册事件,指向事件源(给谁注册的事件就指向谁)

<button>按钮</button>
   <script>
    let btn = document.querySelector('button')
        btn.onclick = function () {
            console.log(this)   // btn
        }
   </script>

7、定时器里面的回调函数this指向window

// 当定时器结束后,里面的回调函数被当作普通函数使用,所以this指向window
setTimeout(function(){
      console.log(this)   // window
    },1000)

8、箭头函数没有this,它内部this由所处作用域(上下文)决定,call/apply/bind也不能改变箭头函数this

    const obj = {
      value: 10,
      getValue: function () {
        // 传统函数  
        function normalFunction() {
          console.log(this)  // window (这里的 this 指向全局对象(在浏览器中是 window),因为                                        // normalFunction 是作为一个普通函数调用,而不是 obj 的方法)
        }
        // 箭头函数  
        const arrowFunction = () => {
          console.log(this)  // obj(这里的 this 指向 obj,因为箭头函数捕获了定义时的上下文(即 obj 的方法                              // getValue
        }
        normalFunction()
        arrowFunction()
      }
    }
    obj.getValue()

9、构造函数里面的this,指向实例化对象

function Person(name) {
    this.name = name   // 指向实例化对象
    console.log(this)   // 指向实例化对象
}
let p = new Person()   // Person{}

10、构造函数,静态成员中的 this 指向它的构造函数。静态属性和静态方法都是定义在构造函数或类本身上的,不是定义在类的实例上。因此,当你在静态方法中使用 this 关键字时,它指的是定义该静态方法的构造函数或类

    function Person(name, age) {
      // 省略实例成员
    }
    // 静态属性
    Person.eyes = 2
    // 静态方法
    Person.walk = function () {
      console.log('^_^人都会走路...')
      console.log(this.eyes)    // 2
      console.log(this)   // 这里的this指向调用该方法的构造函数,因为Person既是构造函数,也是一个对象
    }                   
   Person.walk()   // Person{} (this指向调用者Person)

11、构造函数内的方法的this(实例方法的this)指向实例化对象

 function Person(name, age) {
      // 实例属性  
      this.name = name;
      this.age = age;

      // 实例方法  
      this.greet = function () {
        console.log(`Hello, my name is ${this.name},my age is ${this.age}`);
      }
    }
    let person = new Person('小十七',23)
    person.greet()    // Hello, my name is 小十七,my age is 23

12、构造函数的原型对象(prototype)内的this指向构造函数的实例化对象

    function Fn(a, b) {
      this.a = a
      this.b = b
    }
    Fn.prototype.THIS = function () {
      console.log(this)
    }
    let fn = new Fn(1, 2)
    fn.THIS()   // Fn {a: 1, b: 2} ,打印出构造函数的实例化对象
    console.log(fn)   // Fn {a: 1, b: 2}

改变this指向

call()方法

  • 返回值:使用指定的 this 值和参数调用函数后的结果
  • 第一个参数接收一个对象,用于改变this的指向,从第二个参数开始往后都是传递给函数的实参
  • 改变this指向后会立即调用被改变this指向的函数

语法:

fn.call( thisArg , a , b , c...)
let obj = {  
  name: 'Alice'  
}  
function greet() {  
  console.log('Hello, ' + this.name)
}  
greet.call(obj)   // 输出: "Hello, Alice"

apply()方法

  • apply()是一个函数的方法,接收一个对象用于改变this的指向,和一个数组(或类数组对象)解析为参数传给函数
  • 返回值:使用指定的 this 值和参数调用函数的结果
  • 改变this时会立即调用

语法:

fn.apply(thisArg, [Array])

这里有两个参数:

  • thisArg:在fn函数运行时使用的this值。如果thisArg是null或undefined,那么this会被全局对象替代。如果不是对象,那么会被转化成对象。
  • argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给func函数。

这是一个使用apply()的例子:

function fn(a, b) {  
  return a + b  
}  
  
console.log(fn.apply(null, [1, 2]))   // 输出3

在这个例子中,apply()调用func函数,并把数组[1, 2]的元素作为参数。因为this没有被特别指定,所以它默认为全局对象(在浏览器中通常是window)。结果为3,因为1加2等于3

bind()方法

  • 返回值:返回一个新函数(改变this指向之后的函数),不会立即调用
  • bind()是一个方法,用于改变this的指向,第一个参数是this指向,从第二个参数开始是传给函数的实参
  • 使用场景:想改变this指向,又不想调用函数时

语法:

fn.bind(thisArg , a , b , c...)

其中:

  • thisArg:当fn执行时this的值。如果thisArgnullundefined,那么this会被全局对象(window)替代。否则,this就是thisArg
  • arg1, arg2, ...:当调用绑定的函数时,作为前缀传递给目标函数的参数

这是一个简单的例子来演示如何使用bind()

let obj = {  
  x: 10,  
  getX: function() {  
    return this.x 
  }  
}  
let retrieveX = obj.getX
console.log(retrieveX())
// 如果直接这样调用,结果是"undefined",因为此时的this指向全局对象(浏览器环境下的window对象)  
let boundGetX = retrieveX.bind(obj) 
console.log(boundGetX())  // 10  (通过bind方法,我们把this绑定到了obj对象上)

第二个例子:

  <button>按钮</button>
  <script>
    let btn = document.querySelector('button')
    btn.addEventListener('click', function () {
      setTimeout(function () {
        btn.disabled=true  // 直接使用btn变量
      }, 2000)
    })
  </script>
  <button>按钮</button>
  <script>
    let btn = document.querySelector('button')
    btn.addEventListener('click', function () {
       let that = this  //将外部的this赋值给that,外部的this指向btn
      setTimeout(function () {
        that.disabled = true  //通过that就可以获取外部this
      }, 2000)
    })
</script>
  <button>按钮</button>
  <script>
    let btn = document.querySelector('button')
    btn.addEventListener('click', function () {
      setTimeout(function () {
        this.disabled=true
      }.bind(this), 2000)  // 使用bind()方法改变y
    })
  </script>
  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十七同志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值