返回

多面手call、apply和bind的详解和演示

前端


了解call、apply和bind,打开运用Function对象的三种方式。


函数的绑定与执行上下文


JavaScript函数有三种绑定方式:
  • 隐式绑定 - 当使用点运算符(.)调用函数时,this绑定到对象。例如,当您调用一个对象的方法时,this关键字绑定到该对象。
  • 显式绑定 - 使用call、apply或bind方法调用函数时,可以显式地绑定this关键字。
  • 硬绑定 - 使用bind方法创建新的函数时,可以将this关键字硬编码到函数中。

1. 隐式绑定:


在JavaScript中,函数的执行上下文由以下因素决定:

  • 函数的调用方式
  • 函数定义时的词法作用域

隐式绑定是默认的绑定方式,当您使用点运算符(.)调用函数时,this关键字绑定到调用该函数的对象。例如:

const person = {
  name: 'John',
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // "Hello, my name is John"

在上面的例子中,当我们调用person.greet()时,this关键字绑定到person对象,因为我们使用了点运算符(.)调用函数。因此,this.name等同于person.name,输出"Hello, my name is John"。

2. 显示绑定:


显示绑定允许您显式地绑定this关键字。您可以使用call、apply或bind方法来实现显示绑定。

  • call方法:

call方法接受两个参数:

  • 要调用的函数
  • 要绑定到this关键字的对象

call方法将this关键字绑定到第二个参数,然后调用函数。例如:

const person = {
  name: 'John'
};

function greet() {
  console.log(`Hello, my name is ${this.name}`);
}

greet.call(person); // "Hello, my name is John"

在上面的例子中,我们使用call方法将this关键字绑定到person对象,然后调用greet()函数。因此,this.name等同于person.name,输出"Hello, my name is John"。

  • apply方法:


    apply方法与call方法类似,但它接受一个数组作为第二个参数,该数组包含要传递给函数的参数。例如:
const person = {
  name: 'John'
};

function greet(greeting) {
  console.log(`${greeting}, my name is ${this.name}`);
}

greet.apply(person, ['Hello']); // "Hello, my name is John"

在上面的例子中,我们使用apply方法将this关键字绑定到person对象,然后调用greet()函数。我们传递一个数组['Hello']作为第二个参数,该数组包含要传递给greet()函数的参数。因此,this.name等同于person.name,输出"Hello, my name is John"。

  • bind方法:


    bind方法与call和apply方法不同,它不会立即调用函数。相反,它返回一个新的函数,该函数的this关键字已绑定到指定的对象。例如:
const person = {
  name: 'John'
};

function greet() {
  console.log(`Hello, my name is ${this.name}`);
}

const boundGreet = greet.bind(person);

boundGreet(); // "Hello, my name is John"

在上面的例子中,我们使用bind方法将this关键字绑定到person对象,然后返回一个新的函数boundGreet。当我们调用boundGreet()时,this关键字绑定到person对象,输出"Hello, my name is John"。

三种方法的区别


call、apply和bind方法之间最主要的区别在于它们传递参数的方式。
  • call方法接受两个参数:要调用的函数和要绑定到this关键字的对象。参数通过逗号分隔。
  • apply方法接受两个参数:要调用的函数和一个数组,该数组包含要传递给函数的参数。
  • bind方法接受两个参数:要调用的函数和要绑定到this关键字的对象。返回一个新的函数,该函数的this关键字已绑定到指定的对象。

用法举例


### **案例一:**
我们有一个名为Person的类,它有一个名为greet()的方法。我们想使用call方法来调用greet()方法,并将this关键字绑定到一个名为person1的对象。
class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const person1 = new Person('John');
Person.greet.call(person1); // "Hello, my name is John"

### **案例二:**
我们有一个名为greet()的函数,它接受一个参数。我们想使用apply方法来调用greet()函数,并将this关键字绑定到一个名为person1的对象。我们想传递一个数组['Hello']作为参数。
function greet(greeting) {
  console.log(`${greeting}, my name is ${this.name}`);
}

const person1 = {
  name: 'John'
};

greet.apply(person1, ['Hello']); // "Hello, my name is John"

### **案例三:**
我们有一个名为Person的类,它有一个名为greet()的方法。我们想使用bind方法来创建