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 就已经正确指向了设定的对象。
相关推荐
晓13135 分钟前
JavaScript加强篇——第七章 浏览器对象与存储要点
开发语言·javascript·ecmascript
Hockor12 分钟前
用 Kimi K2 写前端是一种什么体验?还支持 Claude Code 接入?
前端
杨进军13 分钟前
React 实现 useMemo
前端·react.js·前端框架
海底火旺15 分钟前
浏览器渲染全过程解析
前端·javascript·浏览器
你听得到1115 分钟前
揭秘Flutter图片编辑器核心技术:从状态驱动架构到高保真图像处理
android·前端·flutter
驴肉板烧凤梨牛肉堡17 分钟前
浏览器是否支持webp图像的判断
前端
Xi-Xu18 分钟前
隆重介绍 Xget for Chrome:您的终极下载加速器
前端·网络·chrome·经验分享·github
摆烂为不摆烂20 分钟前
😁深入JS(九): 简单了解Fetch使用
前端
杨进军21 分钟前
React 实现多个节点 diff
前端·react.js·前端框架
用户408128120038121 分钟前
拓展运算符和剩余参数
前端