MST

星途 面试题库

面试题:JavaScript中箭头函数与普通函数在性能上的主要差异是什么

在JavaScript中,箭头函数和普通函数在性能方面存在一些差异。请阐述箭头函数与普通函数相比,在性能上的主要不同点,并举例说明在何种场景下这些差异会对代码性能产生影响。
36.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

性能主要不同点

  1. 没有自己的 this 绑定
    • 普通函数有自己的 this 值,其值在函数被调用时动态确定(取决于调用方式,如作为对象方法调用、直接调用等)。
    • 箭头函数没有自己的 this,它的 this 继承自外层作用域,在定义时就已经确定,不会被调用方式影响。这在某些场景下减少了 this 指向错误带来的性能损耗排查成本。例如在对象方法中使用普通函数和箭头函数的对比:
const obj = {
    data: 10,
    // 普通函数
    getValue1: function() {
        return function() {
            return this.data;
        }
    },
    // 箭头函数
    getValue2: function() {
        return () => {
            return this.data;
        }
    }
};

const value1 = obj.getValue1()(); // value1 为 undefined,因为内部普通函数的 this 不是指向 obj
const value2 = obj.getValue2()(); // value2 为 10,箭头函数继承了外层函数的 this,指向 obj
  1. 没有 arguments 对象
    • 普通函数内部可以使用 arguments 对象来访问所有传入的参数。
    • 箭头函数没有 arguments 对象,若要访问参数,需通过命名参数或剩余参数(...args)。这在一定程度上减少了内存开销,因为不需要额外维护 arguments 对象。例如:
// 普通函数
function normalFunction() {
    console.log(arguments[0]);
}
normalFunction(10);

// 箭头函数
const arrowFunction = (...args) => {
    console.log(args[0]);
};
arrowFunction(10);
  1. 不能用作构造函数
    • 普通函数可以使用 new 关键字作为构造函数来创建对象实例。
    • 箭头函数不能用作构造函数,若使用 new 调用会报错。从性能角度看,这避免了错误使用箭头函数作为构造函数带来的潜在问题和性能损耗。例如:
// 普通函数作为构造函数
function Person(name) {
    this.name = name;
}
const person1 = new Person('John');

// 箭头函数尝试作为构造函数
const ArrowPerson = (name) => {
    this.name = name;
};
// new ArrowPerson('Jane'); // 会报错,箭头函数不能用作构造函数

对代码性能产生影响的场景

  1. 事件处理函数
    • 当在对象的方法中定义事件处理函数时,如果使用普通函数,可能会因为 this 指向问题导致获取对象属性出错,需要手动绑定 this。例如:
const button = document.getElementById('myButton');
const obj = {
    data: 'Hello',
    handleClick: function() {
        button.addEventListener('click', function() {
            console.log(this.data); // this 指向 window,不是 obj,输出 undefined
        });
    }
};
obj.handleClick();
  • 使用箭头函数则可以避免手动绑定 this,提高开发效率和潜在的性能。例如:
const button = document.getElementById('myButton');
const obj = {
    data: 'Hello',
    handleClick: function() {
        button.addEventListener('click', () => {
            console.log(this.data); // 箭头函数继承外层 this,指向 obj,输出 'Hello'
        });
    }
};
obj.handleClick();
  1. 函数作为数组方法的回调
    • 在数组的 mapfilterreduce 等方法中使用箭头函数,代码简洁且能正确继承外层 this。例如:
const numbers = [1, 2, 3, 4];
const context = { factor: 2 };
const result = numbers.map(function(num) {
    return num * this.factor;
}.bind(context)); // 使用普通函数需要手动 bind this

const arrowResult = numbers.map(num => num * context.factor); // 箭头函数简洁且自动继承外层 this
  • 箭头函数在这种场景下,不仅代码可读性好,在频繁调用数组方法回调时,也避免了手动绑定 this 的性能开销。