Buổi 3: Cấu trúc điều khiển, Hàm & Scope
Loại buổi: Lý thuyết
Thời lượng: 120 phút
Dự án: To-Do App (đã có form nhập liệu từ buổi 2)
🎯 Mục tiêu học tập
Sau buổi học này, bạn sẽ có thể:
- ✅ Sử dụng cấu trúc điều khiển: if/else, switch
- ✅ Sử dụng vòng lặp: for, while, forEach
- ✅ Tạo và gọi hàm (function, arrow function)
- ✅ Hiểu về scope (phạm vi biến)
- ✅ Áp dụng vào việc validate và xử lý dữ liệu
🧠 Nội dung chính
1. Cấu trúc điều khiển (Control Flow)
1.1. if / else / else if
Cú pháp:
if (điều kiện) {
// Code chạy nếu điều kiện đúng
} else {
// Code chạy nếu điều kiện sai
}Ví dụ:
let tuoi = 20;
if (tuoi >= 18) {
console.log('Bạn đã trưởng thành');
} else {
console.log('Bạn chưa trưởng thành');
}
// Nhiều điều kiện
let diem = 8.5;
if (diem >= 9) {
console.log('Xuất sắc');
} else if (diem >= 8) {
console.log('Giỏi');
} else if (diem >= 7) {
console.log('Khá');
} else if (diem >= 5) {
console.log('Trung bình');
} else {
console.log('Yếu');
}Toán tử ternary (rút gọn if/else):
let tuoi = 20;
let thongBao = tuoi >= 18 ? 'Đã trưởng thành' : 'Chưa trưởng thành';
console.log(thongBao); // "Đã trưởng thành"
// Tương đương với:
let thongBao2;
if (tuoi >= 18) {
thongBao2 = 'Đã trưởng thành';
} else {
thongBao2 = 'Chưa trưởng thành';
}1.2. switch / case
Cú pháp:
switch (biểu thức) {
case giá trị 1:
// Code
break;
case giá trị 2:
// Code
break;
default:
// Code mặc định
}Ví dụ:
let thu = 3;
switch (thu) {
case 1:
console.log('Chủ nhật');
break;
case 2:
console.log('Thứ hai');
break;
case 3:
console.log('Thứ ba');
break;
case 4:
console.log('Thứ tư');
break;
case 5:
console.log('Thứ năm');
break;
case 6:
console.log('Thứ sáu');
break;
case 7:
console.log('Thứ bảy');
break;
default:
console.log('Không hợp lệ');
}
// ⚠️ Nhớ dùng break, nếu không sẽ "fall through"So sánh if/else vs switch:
if/else: Dùng cho điều kiện phức tạp, so sánh phạm viswitch: Dùng cho so sánh giá trị cụ thể, code gọn hơn
2. Vòng lặp (Loops)
2.1. for loop
Cú pháp:
for (khởi tạo; điều kiện; bước nhảy) {
// Code
}Ví dụ:
// In số từ 1 đến 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// Output: 1, 2, 3, 4, 5
// In số chẵn từ 0 đến 10
for (let i = 0; i <= 10; i += 2) {
console.log(i);
}
// Output: 0, 2, 4, 6, 8, 10Ví dụ thực tế: Tính tổng từ 1 đến n
let n = 10;
let tong = 0;
for (let i = 1; i <= n; i++) {
tong += i; // tong = tong + i
}
console.log(`Tổng từ 1 đến ${n} là: ${tong}`); // 552.2. while loop
Cú pháp:
while (điều kiện) {
// Code
}Ví dụ:
let i = 1;
while (i <= 5) {
console.log(i);
i++;
}
// Output: 1, 2, 3, 4, 5Ví dụ: Đếm ngược
let dem = 10;
while (dem > 0) {
console.log(dem);
dem--;
}
console.log('Bắt đầu!');2.3. do...while loop
Cú pháp:
do {
// Code (chạy ít nhất 1 lần)
} while (điều kiện);Ví dụ:
let x = 0;
do {
console.log(x);
x++;
} while (x < 5);2.4. for...of (ES6) - Dùng với mảng
let danhSach = ['Nguyễn Văn A', 'Trần Thị B', 'Lê Văn C'];
for (let ten of danhSach) {
console.log(ten);
}
// Output: Nguyễn Văn A, Trần Thị B, Lê Văn C2.5. forEach (Method của mảng)
let danhSach = [1, 2, 3, 4, 5];
danhSach.forEach(function(item) {
console.log(item);
});
// Hoặc dùng arrow function
danhSach.forEach(item => console.log(item));So sánh các vòng lặp:
for: Biết trước số lần lặpwhile: Không biết trước số lần lặpdo...while: Chạy ít nhất 1 lầnfor...of: Duyệt mảng (không cần index)forEach: Method của mảng (gọn, hiện đại)
3. Hàm (Functions)
Hàm là một đoạn code được đặt tên, có thể tái sử dụng nhiều lần.
3.1. Function Declaration
function tenHam(thamSo1, thamSo2) {
// Code
return ketQua;
}
// Gọi hàm
tenHam(giaTri1, giaTri2);Ví dụ:
// Hàm tính tổng
function tinhTong(a, b) {
return a + b;
}
let ketQua = tinhTong(5, 3);
console.log(ketQua); // 8
// Hàm không có return
function inThongBao(ten) {
console.log(`Xin chào ${ten}!`);
}
inThongBao('Nguyễn Văn A'); // "Xin chào Nguyễn Văn A!"3.2. Function Expression
const tenHam = function(thamSo) {
// Code
return ketQua;
};Ví dụ:
const tinhTich = function(a, b) {
return a * b;
};
console.log(tinhTich(4, 5)); // 203.3. Arrow Function (ES6) - KHUYẾN NGHỊ
Cú pháp:
const tenHam = (thamSo) => {
// Code
return ketQua;
};
// Rút gọn (1 dòng)
const tenHam = (thamSo) => ketQua;Ví dụ:
// Dạng đầy đủ
const tinhTong = (a, b) => {
return a + b;
};
// Dạng rút gọn (1 dòng)
const tinhTong2 = (a, b) => a + b;
// 1 tham số: bỏ ngoặc đơn
const binhPhuong = x => x * x;
// Không tham số
const chao = () => console.log('Xin chào!');
console.log(tinhTong(3, 4)); // 7
console.log(binhPhuong(5)); // 25
chao(); // "Xin chào!"So sánh:
// Function Declaration
function tong(a, b) { return a + b; }
// Function Expression
const tong2 = function(a, b) { return a + b; };
// Arrow Function
const tong3 = (a, b) => a + b;3.4. Tham số mặc định
function chao(ten = 'Khách') {
console.log(`Xin chào ${ten}!`);
}
chao(); // "Xin chào Khách!"
chao('Nguyễn Văn A'); // "Xin chào Nguyễn Văn A!"3.5. Return
return: Trả về giá trị và kết thúc hàm- Không có
return: Hàm trả vềundefined
function coReturn() {
return 'Có giá trị';
}
function khongReturn() {
console.log('Không có return');
}
console.log(coReturn()); // "Có giá trị"
console.log(khongReturn()); // undefined4. Scope (Phạm vi biến)
Scope là phạm vi mà biến có thể được truy cập.
4.1. Global Scope (Toàn cục)
let bienToanCuc = 'Tôi có thể dùng ở mọi nơi';
function ham1() {
console.log(bienToanCuc); // ✅ Có thể truy cập
}
function ham2() {
console.log(bienToanCuc); // ✅ Có thể truy cập
}4.2. Function Scope (Phạm vi hàm)
function ham1() {
let bienLocal = 'Chỉ dùng trong hàm này';
console.log(bienLocal); // ✅ OK
}
console.log(bienLocal); // ❌ Lỗi: bienLocal is not defined4.3. Block Scope (Phạm vi khối)
if (true) {
let bienBlock = 'Chỉ trong block này';
const bienBlock2 = 'Chỉ trong block này';
console.log(bienBlock); // ✅ OK
}
console.log(bienBlock); // ❌ Lỗi
// var không có block scope
if (true) {
var bienVar = 'Có thể dùng ngoài block';
}
console.log(bienVar); // ✅ OK (⚠️ không nên dùng)Lưu ý quan trọng:
letvàconstcó block scopevarchỉ có function scope (không có block scope)
4.4. Shadowing (Che biến)
let x = 10;
function ham() {
let x = 20; // Biến x trong hàm "che" biến x ngoài
console.log(x); // 20
}
console.log(x); // 10💻 Ví dụ minh họa
Ví dụ 1: Kiểm tra điểm số
function xepLoai(diem) {
if (diem >= 9) {
return 'Xuất sắc';
} else if (diem >= 8) {
return 'Giỏi';
} else if (diem >= 7) {
return 'Khá';
} else if (diem >= 5) {
return 'Trung bình';
} else {
return 'Yếu';
}
}
console.log(xepLoai(9.5)); // "Xuất sắc"
console.log(xepLoai(7.5)); // "Khá"
console.log(xepLoai(4)); // "Yếu"Ví dụ 2: Validate dữ liệu đầu vào
function kiemTraTuoi(tuoi) {
if (typeof tuoi !== 'number') {
return 'Tuổi phải là số';
}
if (tuoi < 0) {
return 'Tuổi không hợp lệ';
}
if (tuoi < 18) {
return 'Chưa đủ tuổi';
}
return 'Hợp lệ';
}
console.log(kiemTraTuoi(20)); // "Hợp lệ"
console.log(kiemTraTuoi(15)); // "Chưa đủ tuổi"
console.log(kiemTraTuoi(-5)); // "Tuổi không hợp lệ"
console.log(kiemTraTuoi('abc')); // "Tuổi phải là số"Ví dụ 3: Tính giai thừa
function giaiThua(n) {
if (n < 0) return 'Không hợp lệ';
if (n === 0 || n === 1) return 1;
let ketQua = 1;
for (let i = 2; i <= n; i++) {
ketQua *= i;
}
return ketQua;
}
console.log(giaiThua(5)); // 120 (5! = 5*4*3*2*1)Ví dụ 4: Tìm số lớn nhất trong mảng
function timSoLonNhat(mang) {
if (mang.length === 0) return null;
let max = mang[0];
for (let i = 1; i < mang.length; i++) {
if (mang[i] > max) {
max = mang[i];
}
}
return max;
}
let diemSo = [8, 9, 7, 8.5, 9.5];
console.log(timSoLonNhat(diemSo)); // 9.5🧪 Quiz cuối buổi (7 câu)
Câu 1: Kết quả của đoạn code sau là gì?
let x = 5;
if (x > 3) {
console.log('A');
} else if (x > 10) {
console.log('B');
} else {
console.log('C');
}A. A
B. B
C. C
D. Không có output
Đáp án: A
Câu 2: Thiếu gì trong switch case sau?
switch (x) {
case 1:
console.log('Một');
case 2:
console.log('Hai');
break;
}A. Thiếu default
B. Thiếu break ở case 1
C. Thiếu switch
D. Không thiếu gì
Đáp án: B
Câu 3: Vòng lặp nào chạy ít nhất 1 lần?
A. for
B. while
C. do...while
D. for...of
Đáp án: C
Câu 4: Kết quả của (() => 5)() là gì?
A. undefined
B. 5
C. Lỗi
D. null
Đáp án: B (IIFE - Immediately Invoked Function Expression)
Câu 5: Scope của biến let trong block {} là gì?
A. Global
B. Function
C. Block
D. Tất cả đều đúng
Đáp án: C
Câu 6: Hàm nào sau đây KHÔNG có return?
A. function a() { return 1; }
B. const b = () => 2;
C. function c() { console.log(3); }
D. Tất cả đều có return
Đáp án: C
Câu 7: Kết quả của đoạn code sau?
let x = 1;
function test() {
let x = 2;
console.log(x);
}
test();
console.log(x);A. 2, 1
B. 1, 2
C. 2, 2
D. 1, 1
Đáp án: A
📝 Bài tập về nhà (chuẩn bị cho buổi 4)
Tạo hàm
kiemTraCongViec(tenCongViec)kiểm tra:- Tên công việc không được rỗng
- Tên công việc phải có ít nhất 3 ký tự
- Trả về
truenếu hợp lệ,falsenếu không
Tạo hàm
tinhTongCongViec(soLuong)dùng vòng lặp tính tổng số công việc từ 1 đến nDùng switch case để phân loại độ ưu tiên (1: Cao, 2: Trung bình, 3: Thấp)
🔗 Tài liệu tham khảo
Chúc bạn học tập tốt! 🚀