Bài trước: Web nâng cao (2) - JavaScript cho React (1)
1.1
JavaScript cho React (2)
Hàm (function) là một đoạn mã nguồn được đặt tên. Hàm thường
giải quyết một công việc nào đó và có thể tái sử dụng.
JavaScript cho phép bạn có thể tạo ra các hàm bằng nhiều
cách. Tùy theo từng tình huống sử dụng, bạn sẽ chọn phương pháp tạo hàm cho phù
hợp. Trong phần này, bạn sẽ tìm hiểu một số phương pháp định nghĩa hàm và các nội
dung liên quan đến hàm như truyền đối số cho hàm, hàm trả về một đối tượng
(object).
1.1.1
Hàm
Định nghĩa bằng từ khóa function
Cách đơn giản và quen thuộc để định nghĩa (hay khai báo) một
hàm là sử dụng từ khóa function, theo sau là tên của hàm, tiếp theo là dấu (),
sau cùng là nội dung của hàm. Nội dung của hàm được đặt trong cặp dấu {}. Ví dụ,
// định nghĩa hàm
function xinChao() {
console.log('Chào bác Tèo');
}
Khi đã định nghĩa hàm, bạn có thể gọi nó để thực thi.
// gọi hàm để thực thi
xinChao();
Mở cửa sổ console của trình duyệt để xem kết quả.
Định nghĩa hàm kiểu biểu thức (function
expression)
Với JavaScript, ngoài việc dùng từ khóa function để định
nghĩa hàm, bạn có thể định nghĩa hàm như là một vế của biểu thức gán.
JavaScript xem một hàm như là một kiểu dữ liệu cơ sở (như
string, number), do vậy hàm cũng là một đối tượng, từ đó bạn có thể định nghĩa
hàm như là phần nội dung (vế phải) của một biểu thức gán, sau đó gán hàm cho một
biến. Ví dụ:
// định nghĩa hàm và gán vào biến chao
const chao = function() {
console.log('Chào bác Tèo');
}
// xuất nội dung hàm ra màn hình
console.log(chao);
// gọi hàm để thực thi
chao();
Một điều cần để ý là hàm được khai báo bằng từ
khóa function có tính chất hoisting, còn hàm định nghĩa bằng kiểu biểu thức thì
không có tính chất này. Hoisting là tính chất cho phép bạn gọi hàm để thực thi
(sử dụng) trước khi định nghĩa. Từ hoist có nghĩa là nổi lên, hiểu nôm na là dù
bạn định nghĩa hàm ở đâu trong chương trình thì JavaScript cũng sẽ cho đoạn mã khai
báo nổi lên đầu của chương trình.
Ví dụ, bạn có thể viết đoạn chương trình theo
kiểu dưới đây, nó vẫn chạy được bình thường,
// gọi hàm trước khi định nghĩa
xinChao();
// định nghĩa hàm
function xinChao() {
console.log('Chào bác Tèo');
}
Tuy nhiên, cũng đoạn mã trên, nếu bạn khai
báo hàm theo kiểu biểu thức, thì sẽ có lỗi:
// gọi hàm trước khi định nghĩa
xinChao();
// định nghĩa hàm
const xinChao = function() {
console.log('Chào bác Tèo');
}
Hàm “mũi tên” (arrow function)
Đây là cách thứ ba để định nghĩa một hàm
trong JavaScript. Bạn có thể sử dụng dấu mũi tên (arrow, =>) để định nghĩa một
hàm. Bạn hãy quan sát ví dụ sau:
Chúng ta sẽ bắt đầu bằng việc định nghĩa một
hàm theo kiểu thông thường, dùng từ khóa function:
// viết hàm trả về bình phương của một số
function square(x) {
return x * x;
}
console.log(square(2));
Tiếp theo, chúng ta sẽ biến đổi cách khai báo
hàm dùng từ khóa function thành kiểu biểu thức, khi đó hàm sẽ không có tên (anonymous
function), vì vậy, chúng ta sẽ gán hàm cho một biến:
// viết hàm trả về bình phương của một số
const square = function(x) {
return x * x;
}
console.log(square(2));
Sau hai bước trên, giờ chúng ta sẽ bỏ từ khóa
function đi, thêm dấu mũi tên (=>), nội dung của hàm sẽ nằm sau dấu mũi tên.
var square = (x) => {
return x * x;
}
console.log(square(2));
Vì nội dung của hàm chỉ có một hàng, nên sẽ bỏ
dấu ngoặc nhọn {}, bỏ luôn chữ return đi cũng được. Cuối cùng chúng ta có hàm
được định nghĩa theo kiểu mũi tên:
const square = (x) => x * x;
console.log(square(2));
Ví dụ, viết lại hàm tính tổng từ 1 > n bằng
cách dùng hàm kiểu “mũi tên”. Nếu hàm có nhiều dòng lệnh thì dùng dấu {} để bao
lại mã nguồn.
const sum = (n) => {
let total = 0;
for(let i = 1; i <= n; i++) {
total += i;
}
return total;
}
console.log(sum(5));
Truyền đối số cho hàm
Trong lập trình, có hai thuật ngữ hay được sử
dụng với ý nghĩa khá giống nhau là tham số (parameter) và đối số (argument). Cả
hai đều ám chỉ đến dữ liệu sẽ được truyền vào cho một hàm. Tuy nhiên, nếu phải
phân biệt rõ ràng hai thuật ngữ này thì bạn có thể hiểu là:
– Tham số (parameter): là dữ liệu cần truyền
cho hàm (khi định nghĩa hàm), dữ liệu được đại diện bằng các cái tên
– Đối số (argument): là giá trị của dữ liệu truyền
cho hàm (khi gọi hàm để thực thi), nói cách khác, đối số chính là giá trị sẽ
truyền vào cho các tham số
Ví dụ,
// n chính là tham số, là cái cần phải truyền cho hàm khi định nghĩa
function sum(n) {
// trả về tổng từ 1 tới n
let total = 0;
for(let i = 1; i <= n; i++) {
total += i;
}
return total;
}
// 5 chính là đối số, là giá trị truyền cho tham
số của hàm khi thực thi
console.log('Ket qua la: ' + sum(5));
Hàm không xác định trước số
tham số
JavaScript cho phép khi định nghĩa hàm không cần
xác định trước số tham số. Tuy nhiên, khi thực thi thì truyền bao nhiêu đối số
cũng được. Để ý tính chất này khi làm việc với hàm callback.
function anyFunction() {
return arguments;
}
console.log(anyFunction(1,2, 'hello', true));
// [Arguments] {
'0': 1, '1': 2, '2': 'hello', '3': true }
Ở ví dụ trên, khi định
nghĩa hàm anyFunction(), bạn không
khai báo là sẽ truyền vào bao nhiêu tham số. Nhưng khi sử dụng, bạn đã truyền
vào 4 đối số, với các kiểu dữ liệu khác nhau. Lưu ý, với mỗi hàm, JavaScript tự
tạo ra một biến kiểu mảng, có tên là arguments, biến này chứa các đối số đã được
truyền vào cho hàm khi nó thực thi. Đoạn mã trên đã thực hiện xuất dữ liệu của
mảng arguments.
Gán giá trị mặc định cho tham số
Bạn có thể gán giá
trị mặc định cho tham số, để khi thực thi hàm, nếu người dùng không truyền giá
trị cho tham số, thì hàm sẽ sử dụng giá trị mặc định để thực thi mà không sinh
ra lỗi. Ví dụ:
function xinChao(name='Teo') {
console.log(`Chao bac ${ name }` );
}
// không truyền giá trị cho đối số
console.log(xinChao());
// có truyền giá trị cho đối số
console.log(xinChao('Ti'));
Khi
thực thi một hàm, nó có thể xuất trực tiếp dữ liệu ra cửa sổ console (như hàm
xinChao), hoặc trả về một giá trị, xem ví dụ sau:
function sum() {
// trả về tổng từ 1 tới 10
let total = 0;
for(let i = 1; i <= 10; i++) {
total += i;
}
return total;
}
console.log('Ket qua la: ' + sum());
Đối tượng trong JavaScript được định nghĩa bằng cặp dấu {},
bên trong là các thuộc tính và phương thức, được biểu diễn dưới dạng name : value. Ví dụ:
const sinhVien = {
ho : 'Nguyen Van',
ten : 'Teo'
}
console.log(sinhVien);
Ngoài cách định nghĩa đối tượng theo kiểu cố định như trên,
bạn có thể tạo ra các đối tượng theo kiểu động bằng cách sử dụng hàm.
Ví dụ: xem xét hàm có tên là sinhVien, hàm này trả về một đối
tượng dựa vào các đối số truyền vào. Thông thường sẽ định nghĩa như sau:
const sinhVien = (hoSV, tenSV) => {
ho : hoSV,
ten : tenSV
};
console.log(sinhVien('Nguyen Van', 'Teo'));
Chạy đoạn chương trình trên sẽ bị lỗi. Hàm trả về một đối tượng
thì cần bao lại nội dung của hàm bằng cặp dấu ngoặc tròn ( ). Chạy hàm sau sẽ
không có lỗi.
const sinhVien = (hoSV, tenSV) => ({
ho : hoSV,
ten : tenSV
});
console.log(sinhVien('Nguyen
Van', 'Teo'));
1.1.2
Xem và đọc thêm
– Sử dụng các từ khóa sau để tìm kiếm trên mạng, đọc và xem
thêm: hàm trong JavaScript, function declarations, function expressions, sự
khác nhau giữa regular function và arrow function.
– [1] Alex Banks, Eve Porcello, Learning React – Mordern Patterns
for Developing React Apps, O’Reilly Media, 2020, p12 – p17
1.1.3 Bài tập và thực hành
Bài tập 1. Viết lại các đoạn mã trong phần lý thuyết để chạy và
kiểm tra lại kết quả.
Bài tập 2. (Tham khảo trên www.w3resource.com)
Write a JavaScript function that reverse a number. Using 3
types of function, including normal function, expression function and arrow
function.
Sample Data and output:
Example x = 32243;
Expected Output: 34223
Bài tập 3. (Tham khảo trên www.w3resource.com)
Write a JavaScript function that returns a passed string
with letters in alphabetical order.
Example string: 'webmaster'
Expected Output: 'abeemrstw'
Note: Assume punctuation and numbers symbols are not
included in the passed string.
[Gợi ý]
Bài tập 2.
Write a JavaScript function that reverse a number. Using 3
types of function, including normal function, expression function and arrow
function.
Sample Data and output:
Example x = 32243;
Expected Output: 34223
– Normal function
function reverse_a_number(n){
// convert number into string
n = n + "";
// convert string into array
const arr = n.split("");
// reverse array
arr.reverse();
// convert array into string
const str = arr.join("");
// convert string into number
n = Number(str);
// another way
return n;
/*another way
n = n + "";
return
Number(n.split("").reverse().join(""));
*/
}
console.log(reverse_a_number(1234));
– Expression function
const reverse_a_number = function(n){
n = n + "";
return Number(n.split("").reverse().join(""));
}
console.log(reverse_a_number(1234));
– Arrow function
const reverse_a_number = (n) => {
n = n + "";
return Number(n.split("").reverse().join(""));
}
console.log(reverse_a_number(1234));
Bài tập 3. (Tham khảo trên www.w3resource.com)
Write a JavaScript function that returns a passed string
with letters in alphabetical order.
Example string: 'webmaster'
Expected Output: 'abeemrstw'
Note: Assume punctuation and numbers symbols are not
included in the passed string.
const alphabetical_order = (str) => {
// convert string into array
const arr = str.split("");
// sorting array in alphabetical order
arr.sort();
// convert array into string
str = arr.join("");
return str;
/* another solution
return
str.split("").sort().join("");
*/
}
console.log(alphabetical_order("webmaster"));
1.1.4
Câu hỏi ôn tập
Câu 1. Trong JavaScript, hàm hoisting được hiểu là gì?
A. Là tính chất cho phép sử dụng hàm trước khi định nghĩa
B. Là hàm được định nghĩa bằng dấu mũi tên (arrow)
C. Là hàm được định nghĩa bằng biểu thức (expression)
D. Đối số truyền cho hàm chính là một hàm
Câu 2. Trong JavaScript có thể định nghĩa hàm bằng cách?
A. Dùng từ khóa function
B. Dùng biểu thức gán
C. Dùng dấu mũi tên
D. Cả 3 cách trên
Câu 3. Đoạn mã JavaScript const square = (x) => x * x; làm
gì ?
A. Gán giá trị x vào
biến square
B. So sánh x với x*x, kết quả trả về biến square
C. Đoạn mã không hợp lệ
D. Định nghĩa hàm square
Câu 4. Đoạn mã JavaScript này xuất gì ra cửa sổ console?
const chao = function() {
console.log('Chào
bác Tèo');
};
console.log(chao);
A. Xuất chữ “chao”
B. Xuất chuỗi “Chào bác Tèo”
C. Xuất nội dung của hàm chao()
D. Báo lỗi tham chiếu
Đáp án: 1 (A), 2 (D), 3 (D), 4 (C)