1. Hàm mũi tên trong JavaScript là gì?

Arrow function hay hàm mũi tên thực chất chỉ là một cách khai báo hàm mà thôi. Nó không phải định nghĩa gì quá phức tạp, ta chỉ cần coi nó như tên gọi thôi. Nó là một cú pháp ngắn gọn dùng để viết hàm trong Js. Arrow function được biểu diễn bởi ký tự mũi tên => , và bằng cách sử dụng Arrow function, chúng ta có thể đơn giản hóa việc khai báo các hàm ẩn danh trong JavaScript.

Một ví dụ đơn giản trước về Arrow function nhé:

<script>
let myFunction = (a, b) => a * b;
document.write(myFunction(4, 5));
</script>

Ở ví dụ này ta đã thấy luôn sự ngắn gọn nhất định. Bình thường ta cần từ khóa function với hàm nhưng để tạo hàm mũi tên thì không.

Các hàm mũi tên đặc biệt hữu ích khi truyền một hàm dưới dạng tham số cho một hàm bậc cao hơn, chẳng hạn như khi bạn lặp qua một mảng với các phương thức trình vòng lặp tích hợp sẵn . Viết tắt cú pháp của chúng cũng có thể cho phép bạn cải thiện khả năng đọc mã của bạn .

2. Quy tắc và cú pháp cơ bản cho hàm mũi tên trong JavaScript

Đầu tiên, các tham số nên được truyền trong ngoặc đơn nhỏ. Bạn có thể tạo một hàm mũi tên với tham số như cú pháp sau:

const myFunction = (arg1, arg2,… argN) => ( statement(s) )

Trong đó:

  • myFunction là tên của hàm
  • arg1, arg2,… argN là các đối số của hàm
  • statement(s) là chức năng của hàm

Ví dụ:

<script>
var hello;

hello = (val) => "Hello " + val;

document.write(hello("lập trình từ đầu!"));
</script>

Nếu chỉ có một tham số được truyền, thì dấu ngoặc đơn là tùy chọn và bạn có thể chọn bỏ qua chúng. Bạn có thể tạo một hàm mũi tên với một tham số như dưới đây:

let myFunction = (arg1, arg2,… argN) => expression

Ví dụ:

<script>
var hello;

hello = val => "Hello " + val;

document.write(hello("lập trình từ đầu!"));
</script>

Nếu không có tham số, thì bạn phải có dấu ngoặc đơn trống – nó không thể được viết mà không có chúng. Vì vậy, bạn có thể viết một hàm không có tham số bằng cách sử dụng hàm mũi tên như được thấy ở đây:

var add = () => { document.write("hey foo") };

Ví dụ:

<script>
var hello;

hello = () => {
  return "Hello World!";
}

document.write(hello());
</script>

Bạn có thể viết lại hàm như được thấy bên dưới mà không cần sử dụng dấu ngoặc đơn trong thân hàm và câu lệnh return :

<script>
var hello;

hello = () => "Hello World!";

document.write(hello());
</script>

Lưu ý

Điều này chỉ hoạt động nếu hàm chỉ có một câu lệnh.

3. Hàm mũi tên với thông số nghỉ và tham số mặc định

Hàm mũi tên Js hỗ trợ một tính năng ES6 khác: các tham số nghỉ. Bạn có thể sử dụng tham số phần còn lại với chức năng mũi tên như trong ví đụ sau:

var add = (num1, num2, ...restparam) => {
    console.log(restparam.length);
    var result = num1 + num2;
    return result;
}
 
var r = add(67, 8, 90, 23);
document.write(r);

Trong ví dụ được thấy ở đây, khi bạn sử dụng tham số phần còn lại với hàm mũi tên, bạn sẽ nhận được đầu ra là 2 và 75 vì số lượng tham số phụ được truyền là 2 và tổng của num1num2 là 75.

Ngoài ra, chức năng mũi tên Js hỗ trợ một tính năng ES6 khác: tham số mặc định. Bạn có thể sử dụng một tham số mặc định với chức năng mũi tên như trong ví dụ sau:

var add = (num1 = 9, num2 = 8) => {
    var result = num1 + num2;
    return result;
}
 
var r = add();
document.write(r);

Trong danh sách trên, chúng ta đang sử dụng các tham số mặc định với chức năng mũi tên. Ta không chuyển bất kỳ giá trị nào trong khi gọi hàm và do các tham số mặc định, đầu ra sẽ là 17.

4. Sử dụng this với hàm mũi tên trong JavaScript

This là một khái niệm có thể phức tạp để nắm bắt, vì nó thay đổi rất nhiều tùy thuộc vào ngữ cảnh và cũng khác nhau tùy thuộc vào chế độ Js(chế độ nghiêm ngặt hay không). Và mình cũng đã nói ở bài trước rồi nên các bạn có thể xem qua nhé.

Bên trong một hàm thông thường, từ khóa this đề cập đến hàm mà nó được gọi. Trong các hàm thông thường, this đại diện cho đối tượng được gọi là hàm, có thể là cửa sổ, tài liệu, nút hoặc bất cứ thứ gì. Với các hàm mũi tên, this luôn đại diện cho đối tượng đã xác định hàm mũi tên.

Lý thuyết có vẻ nghe hơi khó hiểu thì hãy vào ví dụ để cho dễ hiểu hơn nhé.

Cả hai ví dụ sau đều gọi một phương thức hai lần, lần đầu tiên khi tải trang và một lần nữa khi người dùng nhấp vào một nút.

  • Với một hàm thông thường this đại diện cho đối tượng gọi hàm:
<p>Ví dụ này chứng minh rằng trong một hàm thông thường, từ khóa "this" đại diện cho các đối tượng khác nhau tùy thuộc vào cách hàm được gọi.</p>
<p>Nhấp vào nút để thực thi chức năng "hello" một lần nữa, và bạn sẽ thấy rằng lần này "this" đại diện cho đối tượng nút. </p>

<button id="btn">Click Me!</button>
<p id="demo"></p>

<script>
var hello;

hello = function() {
  document.getElementById("demo").innerHTML += this;
}

window.addEventListener("load", hello);

document.getElementById("btn").addEventListener("click", hello);
</script>


  • Với một hàm mũi tên this thể hiện chủ sở hữu của hàm:
<p>Ví dụ này chứng minh rằng trong Hàm mũi tên, từ khóa "this" đại diện cho đối tượng sở hữu hàm, bất kể ai gọi hàm.</p>
<p>Nhấp vào nút để thực thi chức năng "hello" một lần nữa, và bạn sẽ thấy rằng "this" vẫn đại diện cho đối tượng window.</p>

<button id="btn">Click Me!</button>

<p id="demo"></p>

<script>
var hello;

hello = () => {
  document.getElementById("demo").innerHTML += this;
}

window.addEventListener("load", hello);
document.getElementById("btn").addEventListener("click", hello);
</script>

Kết quả cho thấy rằng ví dụ đầu tiên trả về hai đối tượng khác nhau (cửa sổ và nút), và ví dụ thứ hai trả về đối tượng cửa sổ hai lần, vì đối tượng cửa sổ là “chủ sở hữu” của hàm.

5. Sử dụng hàm mũi tên trong Map và Filter

Một trong những nơi phổ biến nhất mà bạn có thể thấy hàm mũi tên là với các phương thức mảng Js như Map, Filter, Reduce… Bằng cách sử dụng hàm mũi tên với các phương thức này bạn có thể thực hiện các phép biến đổi mảng hoàn chỉnh trong một dòng.

Ví dụ:

const twoArray = [1,2,3,4].map( num=>num*2);

Hay

const filterArray = [1,2,3,4].filter( num => num % 2 == 0);

6. Một số hạn chế của hàm mũi tên trong JavaScript

Có một vài hạn chế áp dụng cho các chức năng mũi tên cần lưu ý:

  • Hàm mũi tên không có đối tượng đối số.
  • Hàm mũi tên không thể được sử dụng với toán tử mới để nó không thể hoạt động như một hàm tạo.
  • Hàm mũi tên không có thuộc tính nguyên mẫu .

Nếu bạn cố gắng sử dụng chức năng mũi tên như một hàm tạo, bạn sẽ có một ngoại lệ. Hãy xem xét mã được liệt kê dưới đây:

var foo = (name, age) => { name = name, age = age };
 
var f1 = new foo("cat", 6);

Tại đây, bạn đang cố gắng tạo đối tượng F1 bằng cách sử dụng hàm mũi tên foo làm hàm tạo và JavaScript sẽ ném cho bạn ngoại lệ. Và khi bạn cố in giá trị nguyên mẫu của hàm mũi tên, bạn sẽ nhận được không xác định là đầu ra của mình:

var foo = (name, age) => { name = name, age = age };
 
console.log(foo.prototype);

Chỉ cần nhớ: trong khi hàm mũi tên cung cấp cho bạn các cách viết biểu thức hàm ngắn hơn, nó không có giá trị riêng với this và không thể được sử dụng như một hàm tạo.