返回

call, apply, bind 混淆?拿去手撕吧,隔壁大妈都懂!

前端

你听说过借鸡生蛋 的故事吗?它的原理和 JavaScript 中的 call、apply、bind 方法非常相似。今天,我们就来把这个过程手撕成碎片,让隔壁大妈都能看懂!

一、借鸡生蛋:JavaScript 版

1. 借鸡(挂载方法)

就像借鸡一样,我们先把方法挂载到一个对象上:

const obj = {
  name: 'Tom',
  sayHello: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

2. 生蛋(执行方法)

现在,我们让鸡(方法)生蛋(执行):

obj.sayHello(); // Hello, my name is Tom

3. 还鸡(删除方法)

生完蛋后,我们就把鸡(方法)还回去:

delete obj.sayHello;

二、call、apply、bind 的魔法

call、apply、bind 这三个方法就像借鸡生蛋 中的中间人,它们可以帮助我们实现借鸡、生蛋、还鸡的过程:

1. call

// 借鸡
obj.sayHello.call({ name: 'Jerry' }); // Hello, my name is Jerry

// 生蛋
obj.sayHello.call({ name: 'Jack' }, 'world'); // Hello, world

2. apply

// 借鸡
obj.sayHello.apply({ name: 'Mary' }); // Hello, my name is Mary

// 生蛋
obj.sayHello.apply({ name: 'Lucy' }, ['world']); // Hello, world

3. bind

// 借鸡
const boundHello = obj.sayHello.bind({ name: 'John' });

// 生蛋
boundHello(); // Hello, my name is John

// 还鸡
boundHello.apply({ name: 'Tim' }); // Hello, my name is Tim

三、区别与妙用

1. 参数传递

  • callapply 可以传递参数,而 bind 只能传递借鸡时需要的参数,生蛋时无法再传递参数。
  • apply 的第二个参数必须是数组,而 call 可以直接传递参数。

2. 返回值

  • callapply 返回执行方法后的返回值。
  • bind 返回一个新的函数,该函数可以多次调用,每次调用都使用最初借鸡时传递的参数。

妙用:

  • 借鸡生蛋:call、apply、bind 绑定方法到不同的对象,让这些对象执行不同的操作。
  • 延迟执行:bind 创建一个新函数,该函数可以延迟执行,传递不同的参数。
  • 部分应用:bind 固定一部分参数,生成一个新的函数,该函数只需要传递剩余的参数即可。

四、隔壁大妈也能懂的例子

小明家有一只母鸡,小红想借来生蛋。

  • call: 小明把母鸡借给小红,小红用母鸡生了鸡蛋,鸡蛋是小红的(因为 call 改变了 this 指向)。
  • apply: 小明把母鸡借给小红,小红用母鸡生了鸡蛋,鸡蛋是小明的(因为 apply 不改变 this 指向)。
  • bind: 小明把母鸡借给小红,小红用母鸡生了鸡蛋,鸡蛋是小红的,但是小红可以随时借母鸡生鸡蛋(因为 bind 返回了一个新的函数)。

现在,你懂了吗?隔壁大妈都懂哦!