Hiểu rõ về Arrow Function trong JavaScript ES6

ES6 (ECMAScript 2015) đã giới thiệu một cú pháp hàm mới gọi là Arrow Function (hàm mũi tên). Tên gọi này bắt nguồn từ ký hiệu => được sử dụng để định nghĩa hàm.

Ví dụ cơ bản:

// Arrow Function
const double = x => x * 2;

// Tương đương với hàm thông thường
const doubleRegular = function(x) {
    return x * 2;
};

Arrow Function hoạt động như một hàm ẩn danh (anonymous function) nhưng có cú pháp ngắn gọn hơn. Có hai dạng chính:

  1. Dạng biểu thức đơn (single expression): Không cần dùng từ khóa return và dấu ngoặc nhọn.

    // Chỉ một tham số, thực thi một biểu thức
    const square = x => x * x;
  2. Dạng nhiều câu lệnh: Cần dùng { } và từ khóa return.

    const processValue = x => {
        if (x > 0) {
            return x * x;
        } else {
            return -(x * x);
        }
    };

Cách xử lý tham số:

  • Khi có nhiều tham số hoặc không có tham số, cần dùng dấu ngoặc đơn:

    // Hai tham số
    const sum = (a, b) => a + b;
    
    // Không tham số
    const getPi = () => 3.14159;
    
    // Tham số rest (phần còn lại)
    const sumAll = (a, b, ...others) => {
        let total = a + b;
        for (let num of others) {
            total += num;
        }
        return total;
    };

Trả về đối tượng (object):

Khi muốn trả về một object literal từ arrow function, cần bọc nó trong dấu ngoặc đơn để tránh nhầm lẫn với thân hàm:

// Sai - sẽ gây lỗi SyntaxError
const createUser = name => { username: name };

// Đúng - bọc object trong ()
const createUser = name => ({ username: name });

Giá trị của this trong Arrow Function

Khác biệt quan trọng nhất giữa arrow function và function thông thường nằm ở cách xử lý từ khóa this:

  • Function thông thường: this được xác định tại thời điểm gọi hàm (dynamic binding).
  • Arrow Function: this được xác định dựa trên ngữ cảnh (lexical scope) tại nơi hàm được định nghĩa.

Ví dụ so sánh:

const person = {
    birthYear: 1990,
    getAge: function() {
        // Sử dụng function thông thường - có vấn đề
        const calculate = function() {
            return new Date().getFullYear() - this.birthYear; // this không phải person
        };
        return calculate();
    }
};

// Cách khắc phục với Arrow Function
const personFixed = {
    birthYear: 1990,
    getAge: function() {
        const calculate = () => new Date().getFullYear() - this.birthYear; // this là person
        return calculate();
    }
};

console.log(personFixed.getAge()); // Kết quả đúng

Lưu ý quan trọng:this trong arrow function đã được gắn kết theo lexical scope, nên các phương thức call(), apply(), bind() sẽ không thể thay đổi giá trị của this:

const person = {
    birthYear: 1990,
    getAge: function(year) {
        const calculator = (y) => y - this.birthYear;
        return calculator.call({birthYear: 2000}, year); // this vẫn là person, không phải {birthYear: 2000}
    }
};

console.log(person.getAge(2023)); // Kết quả 33, không phải 23

Thẻ: Arrow Function es6 JavaScript lexical scope this binding

Đăng vào ngày 12 tháng 6 lúc 06:27