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 就已经正确指向了设定的对象。
相关推荐
前端的日常1 分钟前
JavaScript 必看!算法 O 系列全攻略
前端
anganing5 分钟前
Web 浏览器预览 Excel 及打印
前端·后端
Chad6 分钟前
Vue3 + vite 首屏优化加载速度
前端
Ace_317508877616 分钟前
义乌购平台店铺商品接口开发指南
前端
ZJ_19 分钟前
Electron自动更新详解—包教会版
前端·javascript·electron
哆啦美玲19 分钟前
Callback 🥊 Promise 🥊 Async/Await:谁才是异步之王?
前端·javascript·面试
brzhang27 分钟前
我们复盘了100个失败的AI Agent项目,总结出这3个“必踩的坑”
前端·后端·架构
万能的小裴同学34 分钟前
让没有小窗播放的视频网站的视频小窗播放
前端·javascript
今禾1 小时前
# 深入理解JavaScript闭包与柯里化:函数式编程的核心利器
javascript
小小琪_Bmob后端云1 小时前
引流之评论区截流实验
前端·后端·产品