bind 与 call/apply 的区别:一场 JavaScript 函数的 “时空穿越”

146 阅读3分钟

bind 与 call/apply 的区别:一场 JavaScript 函数的 “时空穿越”

如果把 JavaScript 函数比作一位身怀绝技的演员,那 this 就是 TA 脚下的舞台。而 bind、call、apply 这三个方法,就像是舞台调度工具 —— 同样能改变演员的站位,却有着截然不同的 “工作方式”。今天咱们就用一场 “函数舞台剧” 的形式,聊聊这三者的核心区别。

一、call/apply:说走就走的 “即时表演”

想象这样一个场景:演员小明原本在 A 舞台(this 指向 A 对象)表演,突然导演喊:“小明,立刻到 B 舞台救场!” 这时候 call 和 apply 就派上用场了 —— 它们会立即执行函数,并临时切换 this 指向。

// 演员小明的表演脚本
const actor = {
  name: "小明",
  perform: function(role, line) {
    console.log(`${this.name}扮演${role}说:"${line}"`);
  }
};
// 原本在自己的舞台表演
actor.perform("王子", "请嫁给我吧!"); 
// 输出:小明扮演王子说:"请嫁给我吧!"
// 突然被call到新舞台救场
const newStage = { name: "小红" };
actor.perform.call(newStage, "公主", "我愿意!"); 
// 输出:小红扮演公主说:"我愿意!"
// apply的用法类似,只是参数用数组包裹
actor.perform.apply(newStage, ["女巫", "哈哈哈我来啦!"]); 
// 输出:小红扮演女巫说:"哈哈哈我来啦!"

call 和 apply 的区别就像点外卖:call 是 “汉堡、可乐、薯条” 这样逐个报菜名,apply 则是 “[汉堡,可乐,薯条]” 这样递上菜单 —— 核心功能一致,只是参数传递方式不同。

二、bind:预约未来的 “延时演出”

如果导演说:“小明,明天下午 3 点到 B 舞台演出”,这时候就该 bind 登场了。它不会立即执行函数,而是返回一个绑定了新 this 的函数副本,等你需要的时候再调用。

// 预约明天的演出
const tomorrowShow = actor.perform.bind(newStage, "骑士");
// 现在不执行,只是做好准备
// 第二天调用
tomorrowShow("我来守护你!"); 
// 输出:小红扮演骑士说:"我来守护你!"

这个特性让 bind 在异步操作中大放异彩。比如点击按钮时需要保留正确的 this 指向,用 bind 提前 “绑定” 就不会出错:

const button = {
  text: "点击我",
  bindClick: function() {
    // 提前绑定this到button对象
    document.addEventListener("click", function() {
      console.log(this.text);
    }.bind(this));
  }
};
button.bindClick(); 
// 点击页面时输出:点击我(如果不用bind会输出undefined)

三、核心区别对照表

特性call/applybind
执行时机立即执行函数返回函数副本,需手动调用
返回值函数执行结果绑定新 this 的函数
参数传递call 逐个传,apply 数组传预先传入,调用时可补传
典型场景临时借用方法(如数组借用)异步操作绑定 this、柯里化

举个数组借用对象方法的例子,感受下 call 的妙用:

const arrayLike = { 0: "a", 1: "b", length: 2 };
// 让类数组借用数组的push方法
Array.prototype.push.call(arrayLike, "c");
console.log(arrayLike); // {0: "a", 1: "b", 2: "c", length: 3}

而 bind 的柯里化能力(预先传参)也很有趣:

function add(a, b) { return a + b; }
const add5 = add.bind(null, 5); // 预先传入第一个参数5
console.log(add5(3)); // 8(相当于add(5,3))

四、记忆口诀:三句话分清三者

  1. call/apply 是 “马上就办” :改变 this 后立即执行,适合临时救场
  1. bind 是 “先约后办” :返回绑定好的函数,需要时再调用
  1. 参数差异要记牢:call 逗号分隔,apply 数组包裹,bind 预填参数

下次写代码时,想想这场 “函数舞台剧”—— 是需要演员立刻换舞台,还是先预约档期?想清楚这个问题,就能准确选用最合适的 “舞台调度工具” 啦!