返回

手写call、apply、bind三剑客,轻松掌控函数指针

前端

前言

提到改变this的指向,首先想到的方式就是callapplybind。对于每种方式底层是如何实现,大多数人不太清楚,如果你还不清楚他们的用法,请移步call、apply、bind。本文会简单讲解他们的用法,底层实现思路,及模拟实现callapplybind

用法

1. call

call()方法允许你将一个函数应用到另一个对象的上下文环境中,即改变this的指向。

function greet(name) {
  console.log(`Hello ${name}!`);
}

const person = {
  name: 'John'
};

// 调用greet函数,将person对象作为this对象
greet.call(person, 'Jane'); // 输出:Hello Jane!

2. apply

apply()方法与call()方法类似,但它接受一个数组作为第二个参数,而不是单独的参数。

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

const numbers = [1, 2, 3];

// 调用sum函数,将numbers数组作为参数数组
const result = sum.apply(null, numbers); // 输出:6

3. bind

bind()方法创建了一个新的函数,该函数将指定的对象作为其this值。

function greet(name) {
  console.log(`Hello ${name}!`);
}

const person = {
  name: 'John'
};

// 创建一个新的函数,该函数将person对象作为this对象
const boundGreet = greet.bind(person);

// 调用boundGreet函数
boundGreet('Jane'); // 输出:Hello Jane!

底层实现思路

1. call

call()方法的底层实现思路是,它通过修改函数的this值来达到改变函数调用的上下文环境的目的。

首先,call()方法将第一个参数(this对象)作为函数的this值。然后,它将剩余的参数作为函数的参数来调用函数。

2. apply

apply()方法的底层实现思路与call()方法类似,但它接受一个数组作为第二个参数,而不是单独的参数。

首先,apply()方法将第一个参数(this对象)作为函数的this值。然后,它将第二个参数(参数数组)中的元素作为函数的参数来调用函数。

3. bind

bind()方法的底层实现思路是,它创建一个新的函数,该函数将指定的对象作为其this值。

首先,bind()方法将第一个参数(this对象)作为新函数的this值。然后,它将剩余的参数作为新函数的参数来创建新的函数。

模拟实现

1. call

Function.prototype.myCall = function (context, ...args) {
  if (typeof this !== 'function') {
    throw new TypeError('Error: Function.prototype.myCall can only be called on functions');
  }

  context = context || window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

2. apply

Function.prototype.myApply = function (context, args) {
  if (typeof this !== 'function') {
    throw new TypeError('Error: Function.prototype.myApply can only be called on functions');
  }

  context = context || window;
  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

3. bind

Function.prototype.myBind = function (context, ...args) {
  if (typeof this !== 'function') {
    throw new TypeError('Error: Function.prototype.myBind can only be called on functions');
  }

  const fn = this;
  return function (...bindArgs) {
    return fn.apply(context, [...args, ...bindArgs]);
  };
};

结语

callapplybind是JavaScript中改变函数this指向的三个重要方法,它们允许你控制函数的this值,从而实现一些强大的功能。了解callapplybind的底层原理,可以帮助你更好地理解JavaScript中的函数指针和高阶函数,并编写出更灵活、可复用的代码。