JS This的指向&改变This指向的三种方法

149 阅读4分钟

笔者目前是前端学习阶段。文章内容如有不足,欢迎评论区留言指出。


在实际开发中,this关键字又是一个非常重要的语法点。甚至可以说对this的掌握熟练程度决定开发速度。

v2-d238f433fc4bbb9db684e9f3c09e1d4b_b.webp

普通函数的this指向

在普通函数中,谨记一句话就是:谁调用This,This指向谁。 在普通函数中,也就是非严格模式下的函数,this通常指向全局对象。在浏览器环境中,全局对象是window

function myFunction() { 
    console.log(this)
} 
myFunction() // Window

普通函数的This是没有那么多要记得,这里就写完了。


箭头函数的This指向

箭头函数和普通函数不同,也不受调用方式的影响,事实上箭头函数中并不存在this 。箭头函数的this指向的是最近层的含有This的普通函数。

function foo() {
    return () => {
        console.log(this)
    }
}
foo()() // window

// 由于箭头函数的this原因,原型对象不推荐使用
function Person(){

}
Person.prototype.foo = () => {
    console.log('已执行')
    console.log(this) 
    // 因为箭头函数没有this 
    // 因此this指向的是最近层的this:window
}
var p = new Person()
p.foo()
</script>

箭头函数的This适用场景

  • 不适用:构造函数、原型函数、dom事件函数等等
  • 适用:引用上层this 在实际开发中,往往根据最合适的使用场景来。

改变This指向的三种方法

方法:

  1. call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。
  2. apply() 方法调用一个函数, 其具有一个指定的this值, 以及作为一个数组(或类似数组的对象
  3. bind() 创建一个函数的实例,在调用时设置 this 关键字为提供的值, 同时可将参数传送到新创建的函数。

使用call()改变This指向

call()可以实现改变This指向。 在call()可以接受任意数量的参数,这些参数会作为函数的参数传递给被调用的函数。其中第一个也是必须要写的参数就是目标指向

const obj = {
    name: '张三',
}
// call() 调用函数 同时指向被调用函数的this
function fn(x, y) {
    console.log(this)
    // 默认指向window call()之后指向()内内容
    console.log(x + y) // 3 
}
fn.call(obj, 1, 2)  // 改变this指向

使用apply()改变This指向

在JavaScript中,apply()方法可以用来改变函数的指向,也就是说,它可以改变this的值。apply()方法接收两个参数:第一个参数是一个函数,第二个参数是this的值。以下是一个简单的例子:

function sayHello() {
  console.log(`Hello, ${this.name}`);
}
const person = {
  name: 'Alice'
};
sayHello.apply(person); // 输出 "Hello, Alice"

在这个例子中,sayHello()函数原本的this值是全局对象(在浏览器中是window,在Node.js中是global),但是通过apply()方法,我们把这个函数的this值改变成了person对象。 此外,apply()方法也可以用来改变函数的参数。你可以把arguments对象(一个类数组对象,包含了函数接收到的所有参数)传递给apply(),这样就可以在函数内部使用这个新的arguments对象。例如:

// apply() 使用场景之求数组最大值
const arr = [1, 2, 3, 4, 5]
console.log(Math.max.apply(null, arr)) // 5

apply()第一个参数可以为null,第二个参数是数组。以上是一个apply()求最大值的例子。

使用bind()改变This指向

call()apply()改变this指向时需要调用函数不同的是,bind()可以不调用函数实现改变指向。

function fn2() {
    console.log(this)
}
// bind返回值为原函数的拷贝
const fun = fn2.bind(obj)
console.log(fun)
fun() // 改变this指向 this:obj

以下是一个给按钮添加点击事件并要求点击后两秒内不可点击的例子:

const btn = document.querySelector('button')
btn.addEventListener('click', function () {
    // 禁用按钮
    this.disabled = true

    // 2s后解除禁用
    /* setTimeout(function () {
        // 解除禁用
        this.disabled = false 
    }, 2000) */ 
    // 由于调用者是window,所以this指向window,解除失败

    // bind()改变指向
    setTimeout(function () {
        // 解除禁用
        this.disabled = false 
    }.bind(this), 2000)
    // .bind(btn)亦可,只是因为this=btn

总结:

  • 普通函数:谁调用This,This指向谁。
  • 箭头函数:箭头函数无this,This指向最近一级有This的函数,开发灵活运用。
  • 改变this指向有三种方法:
  1. call(),可传参数
  2. apply(),可传数组
  3. bind(),不用调用函数就可以改变This指向。