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, Everyone
và Hello, 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ư greet
và greetShort
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) và 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) và 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.