返回

洞悉call、bind、apply的奥妙,游刃有余驾驭this指向

前端

前言:this在JavaScript中的捉摸不定

JavaScript中,this的指向经常让人头疼。它可能是指向当前执行函数的对象,也可能是指向全局对象,还可能指向其他对象。这取决于函数是如何调用的。这种捉摸不定的this指向很容易导致各种问题,比如闭包中this指向错误,或者在面向对象编程中无法访问对象的方法和属性。

call、bind、apply的登场:驯服this指向的利器

为了解决this指向的问题,JavaScript提供了call、bind和apply三个方法。这三个方法都可以用来固定this指向,让我们可以更轻松地控制this指向到哪个对象。

call:显式指定this指向的对象

call方法可以显式地指定this指向的对象。语法如下:

fun.call(thisArg, arg1, arg2, ...)

其中,fun是我们要调用的函数,thisArg是要指定this指向的对象,arg1、arg2、...是要传递给函数的参数。

举个例子,我们有一个对象obj,里面有一个方法sayHello()。我们想要在另一个函数中调用这个方法,但是我们希望this指向obj。这时,我们就可以使用call方法:

function greet() {
  console.log(this.name);
}

const obj = {
  name: 'John Doe',
  sayHello: function() {
    greet.call(this);
  }
};

obj.sayHello(); // 输出:John Doe

apply:与call类似,但参数列表不同

apply方法与call方法类似,但参数列表有所不同。apply方法的参数列表是一个数组,而call方法的参数列表是逗号分隔的。语法如下:

fun.apply(thisArg, [arg1, arg2, ...])

其中,fun是我们要调用的函数,thisArg是要指定this指向的对象,[arg1, arg2, ...]是要传递给函数的参数数组。

举个例子,我们有一个函数sum(),它可以计算两个数的和。我们想要在一个循环中使用这个函数,并把循环中的每个数作为参数传递给sum()。这时,我们就可以使用apply方法:

function sum(a, b) {
  return a + b;
}

const numbers = [1, 2, 3, 4, 5];

for (let i = 0; i < numbers.length; i++) {
  console.log(sum.apply(null, [numbers[i], numbers[i + 1]]));
}

// 输出:
// 3
// 5
// 7
// 9
// 11

bind:返回一个新的函数,this指向固定为指定的对象

bind方法与call和apply方法不同,它不立即调用函数,而是返回一个新的函数。这个新函数的this指向固定为指定的对象。语法如下:

fun.bind(thisArg)

其中,fun是我们要调用的函数,thisArg是要指定this指向的对象。

举个例子,我们有一个对象obj,里面有一个方法sayHello()。我们想要创建一个新的函数,它的this指向固定为obj。这时,我们就可以使用bind方法:

function greet() {
  console.log(this.name);
}

const obj = {
  name: 'John Doe',
};

const sayHello = greet.bind(obj);

sayHello(); // 输出:John Doe

call、bind、apply的区别与适用场景

call、bind、apply三个方法都有异曲同工之处,但也有细微的区别。

  • call和apply都可以立即调用函数,而bind不能。
  • call的参数列表是逗号分隔的,而apply的参数列表是一个数组。
  • bind返回一个新的函数,而call和apply不返回任何值。

在实际开发中,我们可以根据不同的场景选择使用call、bind或apply。

  • 如果我们需要显式地指定this指向的对象,并且希望立即调用函数,那么可以使用call或apply。
  • 如果我们需要显式地指定this指向的对象,但不希望立即调用函数,那么可以使用bind。
  • 如果我们需要把一个函数作为参数传递给另一个函数,那么可以使用bind。

结语

call、bind和apply是JavaScript中非常重要的三个方法,它们可以帮助我们解决this指向的问题。掌握了这三个方法的使用方法和区别,你将能够更好地理解JavaScript的this指向,并编写出更健壮的代码。