返回

别再盲目追随箭头函数了!何时回归普通函数的怀抱

前端

在这个追求简洁、高效的时代,箭头函数以其简洁的语法和隐式返回,在开发人员中备受追捧。然而,一味地追随潮流并不明智,在某些场景下,普通函数反而更胜一筹。

场景 1:需要明确的 this 绑定

箭头函数中的 this 是词法作用域的,这意味着它继承了定义箭头函数的环境中的 this 值。然而,在某些情况下,我们需要明确地绑定 this 值,而箭头函数无法满足这个需求。

const obj = {
  name: 'My Object',
  getName() {
    return this.name;
  }
};

const arrowFn = () => this.name; // undefined

const normalFn = function() { return this.name; }.bind(obj); // 'My Object'

场景 2:需要 arguments 对象

在普通函数中,我们可以使用 arguments 对象来访问所有传递给函数的参数。但是,箭头函数没有自己的 arguments 对象,它们继承了外层函数的 arguments 对象。如果需要访问 arguments 对象,则需要使用普通函数。

function sum() {
  console.log(arguments); // [1, 2, 3]
}

const arrowFn = () => {
  console.log(arguments); // ReferenceError: arguments is not defined
};

场景 3:需要构造函数

箭头函数不能作为构造函数使用,因为它没有自己的 new.target 值。因此,如果需要创建对象实例,则需要使用普通函数。

function Person(name) {
  this.name = name;
}

const arrowFn = () => {
  this.name = 'Default';
};

const person1 = new Person('John'); // Person { name: 'John' }
const person2 = new arrowFn(); // TypeError: arrowFn is not a constructor

场景 4:需要命名函数

在某些情况下,我们需要为函数命名,以便进行调试或堆栈跟踪。普通函数可以使用 function 来命名,而箭头函数则不能。

function greet(name) {
  console.log(`Hello, ${name}!`);
}

const arrowFn = (name) => console.log(`Hello, ${name}!`);

console.log(greet.name); // 'greet'
console.log(arrowFn.name); // ''

场景 5:需要动态函数

有时,我们需要动态地创建函数,并根据不同的情况分配不同的实现。普通函数可以轻松地通过函数表达式或声明来创建,而箭头函数则无法做到这一点。

const createFunction = (type) => {
  if (type === 'greet') {
    return function(name) {
      console.log(`Hello, ${name}!`);
    };
  } else if (type === 'farewell') {
    return function(name) {
      console.log(`Goodbye, ${name}!`);
    };
  }
};

const greetFn = createFunction('greet');
const farewellFn = createFunction('farewell');

结论

虽然箭头函数提供了简洁性和便利性,但它们并非万能之药。在需要明确的 this 绑定、arguments 对象、构造函数、命名函数或动态函数的情况下,普通函数仍然是更好的选择。通过谨慎地选择何时使用箭头函数和何时回归普通函数,我们可以创建可维护、高效且可理解的代码。