Các hàm trong JavaScript

Các hàm trong JavaScript

Bài viết này giải thích về các hàm trong JavaScript.

YouTube Video

Các hàm trong JavaScript

Hàm trong JavaScript là các khối mã có thể tái sử dụng, được dùng để thực hiện các nhiệm vụ cụ thể. Việc sử dụng hàm giúp cải thiện tính dễ đọc của mã và làm cho việc bảo trì trở nên dễ dàng hơn. Hàm có thể được định nghĩa theo nhiều cách và được điều chỉnh linh hoạt bằng các tham số và giá trị trả về.

Các cách định nghĩa hàm

Tuyên bố Hàm

Các hàm có thể được định nghĩa bằng từ khóa function. Các khai báo hàm được nâng lên (hoisted) trước khi mã chạy, vì vậy chúng có thể được gọi trước khi chúng được định nghĩa.

1console.log(greet("Everyone")); // Hello, Everyone
2
3function greet(name) {
4    return "Hello, " + name;
5}
6
7console.log(greet("Alice")); // Hello, Alice

Trong ví dụ này, vì hàm greet được gọi trước khi khai báo, nên Hello, EveryoneHello, Alice được hiển thị.

Biểu thức Hàm

Hàm cũng có thể được định nghĩa bằng cách gán chúng vào một biến. Trong trường hợp này, hàm không được nâng lên (hoisted) và chỉ có thể được gọi sau khi nó được định nghĩa.

1const greet = function(name) {
2    return "Hello, " + name;
3};
4
5console.log(greet("Bob")); // Hello, Bob

Trong ví dụ này, Hello, Bob sẽ được hiển thị.

Hàm Mũi Tên

Hàm mũi tên là một cách để định nghĩa hàm với cú pháp ngắn gọn hơn. Chúng đặc biệt hữu ích khi sử dụng hàm ẩn danh (hàm không có tên). Hàm mũi tên cũng có cách hành xử khác về từ khóa this.

 1const greet = (name) => {
 2    return "Hello, " + name;
 3};
 4
 5// When it can be expressed in a single line,
 6// `return` and curly braces can be omitted
 7const greetShort = name => "Hello, " + name;
 8
 9console.log(greet("Charlie")); // Hello, Charlie
10console.log(greetShort("Dave")); // Hello, Dave

Hàm có thể được khai báo như greetgreetShort trong ví dụ này. Nếu hàm chỉ có một dòng, bạn có thể bỏ qua {} (dấu ngoặc nhọn) như greetShort.

Các yếu tố của một Hàm

Tham số

Các giá trị được truyền vào hàm được gọi là tham số. Bằng cách chỉ định tham số khi định nghĩa một hàm, bạn có thể truyền giá trị khi gọi hàm.

1function add(a, b) {
2    return a + b;
3}
4
5console.log(add(2, 3)); // 5

Đối số mặc định

Bạn có thể chỉ định một giá trị mặc định nếu không có giá trị nào được truyền vào đối số.

1function greet(name = "Guest") {
2    return "Hello, " + name;
3}
4
5console.log(greet()); // Hello, Guest
6console.log(greet("Alice")); // Hello, Alice

Trong ví dụ này, nếu greet() được gọi, giá trị mặc định Guest sẽ được sử dụng.

Giá trị trả về

Bạn có thể trả về một giá trị trả về từ một hàm bằng cách sử dụng câu lệnh return. Nếu không có câu lệnh return, hàm sẽ trả về undefined.

1function greet(name) {
2    console.log('Hello, ' + name + '!');
3}
4function square(num) {
5    return num * num;
6}
7
8console.log(square(4)); // 16
9console.log(greet('Alice')); // undefined

Trong ví dụ này, vì greet không trả về giá trị nào nên giá trị trả về là undefined.

Hàm vô danh

Một hàm không có tên được gọi là hàm vô danh. Chúng thường được sử dụng như các biểu thức hàm hoặc hàm mũi tên.

1const double = function(num) {
2    return num * 2;
3};
4
5console.log(double(5)); // 10

Biểu thức hàm gọi ngay lập tức (IIFE)

Một biểu thức hàm gọi ngay lập tức (IIFE) là một hàm được thực thi ngay khi nó được định nghĩa. Nó thường được sử dụng để kiểm soát phạm vi (scope).

1/* Example of IIFE: Immediately Invoked Function Expression */
2(function() {
3    console.log("This is an IIFE");
4})(); // This is an IIFE

Nó được thực thi ngay khi được khai báo.

Hàm callback

Truyền một hàm làm đối số cho một hàm khác, để thực thi sau, được gọi là một hàm callback. Nó được sử dụng thường xuyên trong xử lý bất đồng bộ và xử lý sự kiện.

1function processData(callback) {
2    let data = "Processed Data";
3    callback(data);
4}
5
6processData(function(result) {
7    console.log(result); // Processed Data
8});

Trong ví dụ này, một hàm xuất giá trị ra console được truyền làm hàm callback.

Hàm đệ quy

Gọi chính hàm đó được gọi là đệ quy, và một hàm thực hiện xử lý lặp lại bằng cách này được gọi là hàm đệ quy. Ví dụ, một hàm để tính giai thừa có thể được triển khai bằng cách sử dụng đệ quy như sau.

 1function factorial(n) {
 2    if (n === 0) {
 3        return 1;
 4    } else {
 5        return n * factorial(n - 1);
 6    }
 7}
 8
 9console.log(factorial(5));
10// Output : 120
11// (5 * 4 * 3 * 2 * 1 = 120)

Trong ví dụ này, giai thừa của 5, tức là 120, sẽ được hiển thị.

Từ khóa this

Từ khóa this được sử dụng trong một hàm chỉ ra đối tượng mà hàm đang tham chiếu tới. Trong một hàm thông thường, nó tham chiếu đến đối tượng gọi, nhưng trong các hàm mũi tên, nó giữ lại this của phạm vi mà nó được định nghĩa.

 1const obj = {
 2    name: "Alice",
 3    greet: function() {
 4        console.log(this.name); // Refers to "Alice"
 5    }
 6};
 7
 8obj.greet(); // Alice
 9
10const obj2 = {
11    name: "Bob",
12    greet: () => {
13        // Arrow function refers to the outer scope (undefined here)
14        console.log(this.name);
15    }
16};
17
18obj2.greet(); // undefined

Phương thức greet của biến obj được khai báo bằng từ khóa function. Do đó, từ khóa this tham chiếu đến đối tượng của biến obj. Mặt khác, phương thức greet của biến obj2 được khai báo bằng một hàm mũi tên (arrow function). Vì vậy, từ khóa this tham chiếu đến đối tượng trong phạm vi bên ngoài và trong ví dụ này giá trị của nó là undefined.

Phạm vi hàm và Closures

Các biến được định nghĩa bên trong một hàm không thể được truy cập từ bên ngoài hàm. Điều này được gọi là phạm vi hàm (function scope). Cũng có một khái niệm gọi là closure, giữ lại phạm vi tại thời điểm hàm được định nghĩa.

 1function outer() {
 2    let outerVar = "I am outer!";
 3
 4    function inner() {
 5        console.log(outerVar); // Can access outerVar
 6    }
 7
 8    return inner;
 9}
10
11const innerFunc = outer();
12innerFunc(); // I am outer!

Trong ví dụ này, hàm inner có thể truy cập biến outerVar vì nó giữ lại phạm vi nơi nó được định nghĩa.

Tóm tắt

  • Có nhiều cách khác nhau để định nghĩa hàm, bao gồm function declarations (khai báo hàm), function expressions (biểu thức hàm)arrow functions (hàm mũi tên).
  • Các hàm có thể nhận các tham số (arguments) và trả về giá trị (values).
  • Có những cách sử dụng đặc biệt như callback functions (hàm gọi lại)recursive functions (hàm đệ quy).
  • Cần phải cẩn thận với cách xử lý this, vì hàm mũi tên (arrow functions) và hàm thông thường hoạt động khác nhau.
  • Closures có thể được sử dụng để truy cập các biến nội bộ từ bên ngoài phạm vi.

Hàm là một trong những khái niệm quan trọng trong JavaScript, tận dụng cấu trúc linh hoạt của nó.

Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.

YouTube Video