Arrow functions trong JavaScript cung cấp một cú pháp ngắn gọn và không có bối cảnh this riêng, nhưng cũng có một số trường hợp bạn nên tránh sử dụng chúng. Dưới đây là một số tình huống mà việc sử dụng arrow functions không phải là lựa chọn tốt:

1. Khi Cần Sử Dụng Bối Cảnh this

Arrow functions không có bối cảnh this riêng; chúng kế thừa this từ ngữ cảnh bao quanh. Điều này có thể gây ra vấn đề khi bạn cần this trỏ đến đối tượng cụ thể. Ví dụ:

function Person() {
    this.age = 0;

    setInterval(() => {
        this.age++; // 'this' trỏ đến đối tượng Person
        console.log(this.age);
    }, 1000);
}

const person = new Person(); // In ra 1, 2, 3, ...

Trong ví dụ này, nếu bạn sử dụng hàm thông thường thay vì arrow function, this sẽ không trỏ đến đối tượng Person.

2. Khi Cần Sử Dụng arguments

Arrow functions không có đối tượng arguments, điều này có thể gây khó khăn trong các tình huống mà bạn cần sử dụng nó:

const sum = (...args) => {
    return args.reduce((acc, val) => acc + val, 0);
};

// Hoặc với hàm thông thường:
function sum() {
    return Array.from(arguments).reduce((acc, val) => acc + val, 0);
}

Sử dụng hàm thông thường trong trường hợp này giúp bạn truy cập đối tượng arguments một cách dễ dàng.

3. Khi Cần Định Nghĩa Phương Thức trong Lớp

Khi định nghĩa phương thức trong một lớp, bạn nên sử dụng hàm thông thường để đảm bảo rằng this trỏ đến đối tượng của lớp. Ví dụ:

class Animal {
    constructor() {
        this.sound = 'Roar';
    }

    // Không nên sử dụng arrow function
    makeSound = () => {
        console.log(this.sound);
    };
}

const lion = new Animal();
lion.makeSound(); // 'Roar'

Ở đây, nếu bạn sử dụng arrow function, phương thức sẽ được gán như một thuộc tính, và this có thể không hoạt động như mong đợi trong các tình huống khác.

4. Khi Cần Khả Năng Kế Thừa

Nếu bạn cần kế thừa từ một phương thức, sử dụng arrow functions sẽ không hoạt động như mong đợi. Ví dụ:

class Base {
    method() {
        console.log('Base method');
    }
}

class Derived extends Base {
    method = () => {
        console.log('Derived method');
    };
}

const obj = new Derived();
obj.method(); // 'Derived method'

// Nhưng phương thức từ lớp cha không thể được gọi trực tiếp
const baseObj = new Base();
baseObj.method(); // 'Base method'

Sử dụng arrow function ở đây sẽ không cho phép kế thừa đúng cách.

5. Khi Cần Sử Dụng Phương Thức call, apply, hoặc bind

Arrow functions không thể được sử dụng với call, apply, hoặc bind vì chúng không có bối cảnh this riêng. Ví dụ:

const obj = {
    value: 42,
};

const arrowFunc = () => {
    console.log(this.value);
};

arrowFunc.call(obj); // undefined

Kết Luận

Mặc dù arrow functions có nhiều lợi ích, nhưng bạn nên cân nhắc các trường hợp này để đảm bảo rằng chúng phục vụ cho nhu cầu cụ thể của bạn. Việc lựa chọn giữa arrow functions và hàm thông thường phụ thuộc vào ngữ cảnh sử dụng và cách thức mà bạn cần quản lý this và các đối tượng khác trong mã của mình.