JS 改变 this 指向的方法

2025-08-06
面试
67

在 JavaScript 中,有三种主要方法可以改变函数中 this 的指向,分别是 call()apply()bind()。这三种方法,初学者经常搞不清楚,面试过程中容易忽略

本文来探讨一下他们的区别

三种方法的思维导图.png

call () 方法

  1. 立即执行函数

  2. 第一个参数是新的 this 指向

  3. 后续参数以逗号分隔传递给函数

```javascript function greet(message) { console.log(${message}, ${this.name}); }

const person = { name: "Alice" };

// 使用 call 改变 this 指向 greet.call(person, "Hello"); // 输出: Hello, Alice

```

apply () 方法 1. 立即执行函数

  1. 第一个参数是新的 this 指向

  2. 第二个参数是数组,数组中的元素作为参数传递给函数 ``` javascript function calculateSum(a, b) { return a + b + this.base; }

const context = { base: 10 };

// 使用 apply 改变 this 指向 const result = calculateSum.apply(context, [5, 3]); console.log(result); // 输出: 18 (5+3+10)

```

bind () 方法

  1. 不会立即执行函数,而是返回一个新的函数

  2. 新函数中的 this 被永久绑定到指定的对象

  3. 可以预先传递部分参数(柯里化)

``` javascript function introduce(age) { console.log(I'm ${this.name}, ${age} years old); }

const person = { name: "Bob" };

// 使用 bind 改变 this 指向,返回新函数 const boundIntroduce = introduce.bind(person); boundIntroduce(25); // 输出: I'm Bob, 25 years old

// 预先传递参数 const boundWithAge = introduce.bind(person, 30); boundWithAge(); // 输出: I'm Bob, 30 years old

```

总结区别

  1. ++call++() 和 apply() 会立即执行函数,而 bind() 返回一个新函数

  2. call() 接收逗号分隔的参数,apply() 接收数组形式的参数

  3. bind() 绑定后,无论如何调用,this 指向都不会改变

在 ES6 中,箭头函数没有自己的 this,它会继承外层作用域的 this,因此以上方法无法改变箭头函数的 this 指向。

this 指向问题

来看一个经典问题

var x = 1;

var obj = {
  x: 2,
  fun: function () {
    var x = 5;
    console.log(this.x);
  },
  fun1: () => {
    var x = 6
    console.log(this.x);
  }
}

var fun = obj.fun;

obj.fun();
fun();
obj.fun1();

这段代码,在浏览器端的输出是

2 1 1

在 node 环境的输出是

2
undefined
undefined

分析如下:

  1. 函数 this 指向调用它本身的对象

  2. obj.fun()表达式中,函数 fun的调用方是 obj。那么 thisobj对象,返回 1

  3. fun()没有任何的调用方,this 指向外层的 global 对象。对于浏览器环境,global 是window 对象,使用 var 声明的变量,都会挂载在 window 对象上。所以 window.x = 1。而 node 环境不会自动挂载,所以这里是 undefined。

  4. obj.fun1()是个箭头函数,它会继承外层作用域的 this,和 3 的获取值一样。

原文地址:https://webfem.com/post/js-this,转载请注明出处