MST

星途 面试题库

面试题:JavaScript 中 call 和 apply 方法的区别及应用场景

请详细阐述 JavaScript 里 call 和 apply 方法的区别,并举例说明在实际开发中它们各自适用的场景。
45.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

call 和 apply 方法的区别

  1. 参数传递方式
    • call 方法的第一个参数是 this 的指向,从第二个参数开始往后,都是传递给函数的参数。例如:func.call(thisArg, arg1, arg2, ...)
    • apply 方法的第一个参数同样是 this 的指向,第二个参数是一个包含所有要传递给函数参数的数组(或类数组对象)。例如:func.apply(thisArg, [arg1, arg2, ...])
  2. 性能差异
    • 一般情况下两者性能差异不大。但在传递大量参数时,由于 call 需要逐个列出参数,代码可能会显得冗长,而 apply 只需要传递一个数组,在这种场景下代码可能更简洁,且从理论上来说,在引擎解析参数时,apply 传递单个数组比 call 传递多个离散参数可能在某些情况下性能略好(但实际中这种差异极难察觉)。

实际开发中的适用场景

  1. call 适用场景
    • 继承:在实现继承时经常使用 call 来调用父类构造函数,确保子类能继承父类的属性。例如:
function Animal(name) {
    this.name = name;
}
Animal.prototype.speak = function() {
    console.log(this.name +'makes a sound.');
};
function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
let myDog = new Dog('Buddy', 'Golden Retriever');
myDog.speak();
  • 函数复用:当有一个通用函数,需要在不同 this 环境下调用时,且参数个数固定且较少。比如有一个格式化日期的函数,在不同对象下调用,且传递少量参数:
function formatDate(date, format) {
    // 日期格式化逻辑
    return formattedDate;
}
let obj1 = { date: new Date() };
let obj2 = { date: new Date('2023 - 10 - 01') };
let formatStr = 'yyyy - MM - dd';
let result1 = formatDate.call(obj1, obj1.date, formatStr);
let result2 = formatDate.call(obj2, obj2.date, formatStr);
  1. apply 适用场景
    • Math.max/min 结合数组使用:当需要获取数组中的最大或最小值时,apply 可以很方便地将数组作为参数传递。例如:
let numbers = [1, 5, 3, 9, 7];
let max = Math.max.apply(null, numbers);
let min = Math.min.apply(null, numbers);
console.log(max); // 9
console.log(min); // 1
  • 函数参数不确定个数时:如果函数接收的参数个数不确定,通过数组收集参数后使用 apply 调用函数会很方便。例如,模拟一个可以接收任意数量参数并计算总和的函数:
function sum() {
    let total = 0;
    for (let i = 0; i < arguments.length; i++) {
        total += arguments[i];
    }
    return total;
}
let numArray = [1, 2, 3, 4];
let result = sum.apply(null, numArray);
console.log(result); // 10