call & apply & bind -高级前端必考

JavaScript 中 call、apply 和 bind 的用法与区别

一、对比

方法 调用方式 参数传递方式 是否立即执行 优点 缺点 典型使用场景
call 立即调用 依次传递多个独立参数 是 灵活改变 this 指向并立即执行,方便传递多个已知参数 参数较多时代码冗长 对象方法调用、函数参数已知的情况
apply 立即调用 传递一个数组(类数组)作为参数 是 适合将数组或类数组作为参数传递,代码简洁 参数必须是数组或类数组 数组参数处理、类数组操作
bind 返回新函数 可预先设定 this 和部分参数 否 可创建新函数,预设 this 和参数,提高代码复用性和灵活性 创建新函数可能增加内存占用 需要预设上下文和参数的场景,如事件处理

二、call 方法

用法

call 方法会调用函数,并将函数内部的 this 指向指定的对象,同时可以传递参数给函数。

语法:

javascript 复制代码
function.call(thisArg, arg1, arg2, ...)

举例

javascript 复制代码
const person = {
  name: "John",
  greet: function(age, hobby) {
    console.log(`Hello, my name is ${this.name}. I am ${age} years old and I like ${hobby}.`);
  }
};

person.greet(30, "reading"); // 直接调用,this 指向 person
// Hello, my name is John. I am 30 years old and I like reading.

const anotherPerson = {
  name: "Jane"
};

person.greet.call(anotherPerson, 25, "cooking"); // 使用 call,this 指向 anotherPerson
// Hello, my name is Jane. I am 25 years old and I like cooking.

优点

  • 可以灵活地改变函数内部的 this 指向,调用函数并立即执行。
  • 能够方便地为函数传递多个参数,参数依次传递。(写的时候很爽,复用的时候太恶心)

缺点

  • 如果参数数量较多,在调用 call 时需要逐个列出参数,代码可能会显得冗长。(所以尽量用apply,因为apply和call的不同就是传参方式,apply中只传一个数据即可)

三、apply 方法 (重点,常用)

用法

apply 方法也用于调用函数,指定函数内部的 this 指向,但它接受一个数组(或类数组对象)作为函数的参数。

语法:

javascript 复制代码
function.apply(thisArg, [argsArray])

举例

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];

const max = Math.max.apply(null, numbers); // 使用 apply,将数组元素作为参数传递给 Math.max
console.log(max); // 5

const person = {
  name: "John",
  greet: function(...args) {
    console.log(`Hello, my name is ${this.name}. I like ${args.join(", ")}.`);
  }
};

const hobbies = ["reading", "cooking", "hiking"];
person.greet.apply(person, hobbies); // 使用 apply 传递数组参数
// Hello, my name is John. I like reading, cooking, hiking.

优点

  • 适合将数组或类数组对象作为参数传递给函数,避免逐个列出参数,使代码更简洁。

缺点

  • 参数必须是一个数组或类数组对象,不能像 call 那样直接传递多个独立参数。(复用的时候很爽)

使用场景

  • 防抖、节流中,可以用apply来更改闭包中return出来的function的this指向,从而可以在方法函数中用this指向来添加业务逻辑

四、bind 方法

用法

bind 方法会创建一个新函数,并将新函数内部的 this 指向指定的对象。调用 bind 不会立即执行函数,而是返回一个新函数,这个新函数可以在后续被调用。

语法:

javascript 复制代码
const newFunction = function.bind(thisArg, arg1, arg2, ...)

举例

javascript 复制代码
const person = {
  name: "John",
  greet: function(time, ...hobbies) {
    console.log(`Good ${time}, my name is ${this.name}. I like ${hobbies.join(", ")}.`);
  }
};

const greetMorning = person.greet.bind(person, "morning");
greetMorning("reading", "cooking"); // Good morning, my name is John. I like reading, cooking.

const anotherPerson = {
  name: "Jane"
};

const anotherGreet = person.greet.bind(anotherPerson, "afternoon");
anotherGreet("hiking", "painting"); // Good afternoon, my name is Jane. I like hiking, painting.

优点

  • 可以预先设定函数的 this 指向和部分参数,创建一个新函数,这个新函数可以在之后被多次调用,提高代码的复用性和灵活性。
  • 在事件处理函数或定时器等场景中非常有用,可以提前绑定好上下文,避免在回调中手动设置 this。

缺点

  • 创建了一个新的函数,如果频繁使用可能会增加内存占用,相比之下 call 和 apply 是直接调用函数。

使用场景

  • 当需要预先设定函数的上下文和部分参数,但又不希望立即执行函数,而是稍后多次调用时。例如,在设置事件监听器时,提前绑定好对象的方法作为事件处理函数,这样在事件触发时,函数内部的 this 就已经正确指向了设定的对象。
相关推荐
涛涛ing12 分钟前
2026年最值得关注的前端变化,藏在“默认值”里
前端
量化分析码农1 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
亿元程序员2 小时前
太牛了!这AI做出来的游戏,居然还能变现!
前端
hellice2 小时前
闪传 FlashDrop 实战:我用 300 行 Node 代码做了个「4 位取件码」临时文件中转站
前端·产品
用户0829773260052 小时前
RTX 5500 MIG 踩坑记录:切分之后模型跑不起来,排错整整一下午
前端
Lank_M2 小时前
AI 放大后的图更清楚,但它不能当原图入库
前端
Swot2 小时前
SvelteKit 数据流研究:`+page.js` 和 `+page.server.js` 到底谁在跑,数据又去了哪儿
前端·后端
用户4147679304153 小时前
Windows 触摸屏上 Swiper 轮播滑不动?可能是内部滚动容器抢走了你的手势
前端
张明君644513 小时前
从一个 Referer 引发的 403,到 SSR 服务失稳:Astro 流式渲染与缓存失效分析
前端
律宏阔3 小时前
微信小程序 + Taro + TDesign 去掉 [&&&],让普通 Tailwind 类接管局部样式
前端·微信小程序·taro