JavaScript cơ bản cho người mới bắt đầu
Trần Thị Vân
- 223
- 25/07/2026
JavaScript là một trong những công nghệ quan trọng nhất của Web. Nếu HTML tạo ra cấu trúc của trang, CSS quyết định cách giao diện hiển thị thì JavaScript đảm nhiệm phần lớn hành vi và tương tác phía người dùng. Khi bấm nút để mở menu, nhập dữ liệu vào biểu mẫu, thay đổi nội dung mà không tải lại trang, kiểm tra thông tin trước khi gửi hoặc xây dựng một ứng dụng web có nhiều trạng thái, JavaScript thường là thành phần đứng phía sau.
Tuy nhiên, người mới học JavaScript rất dễ rơi vào tình trạng biết viết vài dòng mã nhưng chưa hiểu bản chất. Họ có thể nhớ cú pháp if, for hay function nhưng lại lúng túng khi phải kết hợp chúng để giải quyết một bài toán thực tế. Vì vậy, học JavaScript hiệu quả không nên bắt đầu bằng việc ghi nhớ thật nhiều phương thức, mà cần xây dựng một mô hình tư duy rõ ràng: dữ liệu là gì, dữ liệu được lưu ở đâu, chương trình ra quyết định như thế nào, hành động được đóng gói ra sao và các thành phần trong chương trình liên hệ với nhau thế nào.
Trong bài viết này, Web Mới xây dựng lộ trình JavaScript từ nền tảng dành cho người hoàn toàn mới đến những kiến thức đủ chắc để tiếp tục học DOM, xử lý sự kiện, gọi API, lập trình bất đồng bộ và các thư viện, framework hiện đại.

JavaScript đứng ở đâu trong quá trình xây dựng website?
Một website hiện đại thường không được tạo nên bởi một công nghệ duy nhất. Ba công nghệ nền tảng thường được nhắc đến là HTML, CSS và JavaScript, nhưng mỗi công nghệ giải quyết một nhóm vấn đề khác nhau.
| Công nghệ | Vai trò chính | Ví dụ |
|---|---|---|
| HTML | Xây dựng cấu trúc và nội dung | Tiêu đề, đoạn văn, biểu mẫu, danh sách, bảng |
| CSS | Trình bày và bố cục giao diện | Màu sắc, khoảng cách, kích thước, responsive |
| JavaScript | Tạo hành vi và xử lý logic | Nhấp nút, kiểm tra dữ liệu, thay đổi nội dung, gọi API |
Có thể hình dung đơn giản: HTML trả lời câu hỏi “Trang có những gì?”, CSS trả lời “Trang trông như thế nào?”, còn JavaScript trả lời “Trang sẽ làm gì khi người dùng tương tác?”.
Sự phân chia này không có nghĩa JavaScript chỉ dùng để xử lý nút bấm trên trình duyệt. Ngày nay JavaScript còn có thể chạy ở phía máy chủ, xây dựng công cụ dòng lệnh, xử lý dữ liệu, tạo ứng dụng desktop và tham gia vào nhiều loại phần mềm khác. Dù vậy, với người mới bắt đầu, trình duyệt vẫn là môi trường rất phù hợp để hiểu những nguyên lý đầu tiên.
JavaScript khác gì với Java?
Tên gọi dễ khiến người mới tưởng JavaScript là một phiên bản của Java, nhưng đây là hai ngôn ngữ khác nhau. Chúng có lịch sử, mô hình thực thi và hệ sinh thái riêng.
Khi học JavaScript, bạn không cần học Java trước. Những kiến thức về biến, hàm, điều kiện, vòng lặp hay lập trình hướng đối tượng có thể xuất hiện ở nhiều ngôn ngữ, nhưng cú pháp và cách hoạt động cụ thể của JavaScript vẫn cần được học riêng.
JavaScript có bắt buộc phải đi cùng HTML không?
Không. JavaScript là một ngôn ngữ lập trình độc lập. Tuy nhiên, trong phát triển web phía trình duyệt, JavaScript thường tương tác với HTML thông qua DOM. Đây là lý do người học web thường tiếp cận JavaScript sau khi đã có nền tảng HTML và CSS.
Nếu chưa biết HTML, bạn vẫn có thể học cú pháp JavaScript, nhưng sẽ khó hiểu đầy đủ những bài toán thực tế như lấy dữ liệu từ biểu mẫu, thay đổi nội dung phần tử hoặc phản hồi khi người dùng tương tác với giao diện.
Cách JavaScript được thực thi
JavaScript không tự nhiên chạy trong trình duyệt chỉ vì bạn viết một tệp có phần mở rộng .js. Một môi trường thực thi JavaScript cần có bộ máy có khả năng đọc và thực hiện mã lệnh.
Trong trình duyệt, mỗi trình duyệt hiện đại đều có một JavaScript engine. Engine tiếp nhận mã JavaScript, phân tích mã và thực hiện các câu lệnh theo cơ chế của môi trường đó.
Điều quan trọng đối với người mới là hiểu rằng JavaScript không phải một đoạn văn bản được trình duyệt “hiển thị” giống HTML. Nó là chương trình được thực thi để tạo ra kết quả hoặc tác động lên môi trường đang chạy.
Chạy JavaScript trực tiếp trong trang web
Một cách đơn giản để thử JavaScript là đặt mã trong phần tử script của tài liệu HTML.
<script>
console.log("Xin chào JavaScript");
</script>
Khi trang được trình duyệt xử lý, phần mã JavaScript bên trong phần tử này có thể được thực thi.
Tuy nhiên, khi dự án bắt đầu lớn hơn, việc đặt toàn bộ JavaScript trực tiếp trong HTML sẽ nhanh chóng trở nên khó quản lý. Cách phổ biến hơn là tách mã JavaScript thành tệp riêng.
Tạo tệp JavaScript riêng
Ví dụ, bạn có thể tạo tệp có tên app.js và viết:
console.log("Ứng dụng bắt đầu chạy");
Sau đó liên kết tệp JavaScript với trang HTML:
<script src="app.js"></script>
Cách tổ chức này giúp phần giao diện và phần logic được tách biệt rõ hơn. Khi dự án phát triển, bạn cũng dễ tìm, sửa và tái sử dụng mã nguồn.
Câu lệnh đầu tiên và cách đọc mã JavaScript
JavaScript được tạo thành từ các câu lệnh. Mỗi câu lệnh có thể thực hiện một công việc cụ thể như tạo dữ liệu, gọi hàm, kiểm tra điều kiện hoặc thay đổi giá trị.
Ví dụ:
console.log("Web Mới");
Câu lệnh trên gọi phương thức log của đối tượng console để đưa dữ liệu ra khu vực console của môi trường phát triển.
Với người mới, console.log() đặc biệt hữu ích vì nó cho phép quan sát giá trị trong quá trình chương trình chạy. Thay vì đoán một biến đang chứa gì, bạn có thể kiểm tra trực tiếp.
let name = "Web Mới";
console.log(name);
Khi đọc mã JavaScript, đừng cố hiểu cả đoạn chương trình cùng lúc. Hãy chia nó thành những câu hỏi nhỏ: giá trị nào được tạo ra, giá trị đó được lưu ở đâu, câu lệnh nào sử dụng nó và kết quả được tạo ra ở bước nào.
Dấu chấm phẩy có bắt buộc không?
JavaScript có cơ chế tự động chèn dấu chấm phẩy trong một số trường hợp, vì vậy nhiều đoạn mã vẫn hoạt động dù không viết dấu ; ở cuối câu lệnh. Tuy nhiên, người mới nên duy trì một phong cách nhất quán thay vì dựa vào khả năng tự động này để hiểu sai cú pháp.
let age = 20;
console.log(age);
Điều quan trọng hơn dấu chấm phẩy là hiểu ranh giới giữa các câu lệnh và viết mã rõ ràng. Trong dự án thực tế, tính nhất quán của quy ước code thường có giá trị lớn hơn việc tranh luận về việc có nên viết dấu chấm phẩy trong mọi trường hợp hay không.
Biến và cách lưu dữ liệu
Biến là một trong những khái niệm nền tảng nhất của lập trình. Có thể hiểu biến là một tên được dùng để tham chiếu đến một giá trị mà chương trình cần sử dụng.
Ví dụ, nếu chương trình cần lưu tên người dùng, bạn có thể viết:
let name = "Nguyễn Văn A";
Ở đây, name là tên biến và giá trị được gán cho nó là một chuỗi ký tự.
Biến trở nên quan trọng vì chương trình hiếm khi chỉ xử lý một giá trị cố định. Giá trị có thể thay đổi theo dữ liệu người dùng, kết quả tính toán, phản hồi từ máy chủ hoặc trạng thái hiện tại của ứng dụng.
let, const và var
JavaScript cung cấp nhiều cách khai báo biến, nhưng trong mã hiện đại, người mới chủ yếu cần tập trung vào let và const.
Dùng let khi giá trị của biến có khả năng được gán lại:
let score = 10;
score = 20;
Dùng const khi biến không được gán sang một giá trị khác sau lần khởi tạo:
const siteName = "Web Mới";
Điểm cần hiểu kỹ là const không đồng nghĩa với việc mọi dữ liệu bên trong biến đều bất biến. Với các kiểu dữ liệu phức tạp như object hoặc array, điều bị ngăn cản là việc gán lại biến sang một object hoặc array khác, chứ không phải mọi thay đổi bên trong đều bị cấm.
var là cách khai báo biến cũ của JavaScript. Nó vẫn tồn tại vì lý do tương thích, nhưng khi bắt đầu học JavaScript hiện đại, bạn nên ưu tiên let và const để tránh nhiều vấn đề liên quan đến phạm vi biến.
Quy tắc đặt tên biến
Tên biến nên mô tả được dữ liệu mà nó đại diện. Một tên như userName dễ hiểu hơn nhiều so với x nếu biến dùng để lưu tên người dùng.
const userName = "An";
const productPrice = 500000;
let totalQuantity = 3;
JavaScript phân biệt chữ hoa và chữ thường. Vì vậy, userName, username và UserName được xem là những tên khác nhau.
Trong JavaScript, cách đặt tên theo kiểu camelCase rất phổ biến:
const firstName = "An";
const lastName = "Nguyen";
const shippingAddress = "Hà Nội";
Một biến có tên rõ ràng giúp người đọc hiểu mục đích của đoạn mã mà không cần tìm thêm nhiều ngữ cảnh. Đây là thói quen nhỏ nhưng có ảnh hưởng rất lớn khi chương trình trở nên dài.
Các kiểu dữ liệu cần biết đầu tiên
JavaScript có hệ thống kiểu dữ liệu linh hoạt. Người mới không cần học tất cả ngay từ đầu, nhưng cần phân biệt được những kiểu dữ liệu thường xuyên xuất hiện trong chương trình.
String dùng cho dữ liệu dạng văn bản
String đại diện cho chuỗi ký tự. Nó được dùng để lưu tên, địa chỉ, nội dung thông báo, mã sản phẩm và nhiều loại dữ liệu dạng văn bản khác.
const name = "Web Mới";
const message = "Chào mừng bạn đến với website";
JavaScript hỗ trợ nhiều cách tạo chuỗi. Với mã hiện đại, template literal đặc biệt hữu ích khi cần kết hợp biến vào nội dung.
const userName = "An";
const message = `Xin chào ${userName}`;
Cách viết này giúp tạo chuỗi động dễ đọc hơn so với việc nối quá nhiều đoạn văn bản bằng toán tử.
Number dùng cho dữ liệu số
JavaScript sử dụng kiểu number cho nhiều loại giá trị số, bao gồm số nguyên và số thực.
const age = 25;
const price = 199000;
const average = 8.5;
Các phép toán cơ bản có thể thực hiện trực tiếp:
const price = 100000;
const quantity = 3;
const total = price * quantity;
console.log(total);
Khi xử lý tiền tệ, số thập phân hoặc các phép tính yêu cầu độ chính xác cao, cần hiểu thêm về cách máy tính biểu diễn số thực. Đây là vấn đề quan trọng hơn khi ứng dụng bắt đầu xử lý nghiệp vụ tài chính, nhưng người mới nên biết rằng phép tính số thực trong JavaScript không phải lúc nào cũng cho kết quả thập phân “đẹp” như khi tính trên giấy.
Boolean biểu diễn đúng hoặc sai
Boolean chỉ có hai giá trị: true và false. Kiểu dữ liệu này xuất hiện rất nhiều trong điều kiện.
const isLoggedIn = true;
const hasPermission = false;
Ví dụ, chương trình có thể kiểm tra người dùng đã đăng nhập hay chưa:
if (isLoggedIn) {
console.log("Bạn đã đăng nhập");
}
Boolean là nền tảng để chương trình đưa ra quyết định. Khi hiểu rõ boolean, bạn sẽ dễ tiếp cận các biểu thức điều kiện phức tạp hơn.
undefined và null không hoàn toàn giống nhau
undefined thường xuất hiện khi một giá trị chưa được gán hoặc một dữ liệu không tồn tại theo cách mà chương trình đang truy cập.
let userName;
console.log(userName);
Trong khi đó, null thường được dùng để thể hiện một cách có chủ ý rằng hiện tại không có giá trị.
const selectedUser = null;
Hai giá trị này có thể đều biểu thị trạng thái “không có dữ liệu”, nhưng ý nghĩa trong thiết kế chương trình khác nhau. Hiểu sự khác biệt này sẽ giúp bạn đọc dữ liệu từ API, xử lý biểu mẫu và kiểm tra điều kiện chính xác hơn.
Toán tử và cách JavaScript tạo ra kết quả
Toán tử là công cụ giúp chương trình thực hiện phép tính, so sánh hoặc kết hợp các giá trị. Đây là bước chuyển quan trọng từ việc chỉ lưu dữ liệu sang việc xử lý dữ liệu.
Toán tử số học
Các phép toán cơ bản gồm cộng, trừ, nhân và chia:
const a = 10;
const b = 3;
console.log(a + b);
console.log(a - b);
console.log(a * b);
console.log(a / b);
Toán tử % trả về phần dư của phép chia:
const number = 10;
console.log(number % 3);
Phần dư rất hữu ích trong những bài toán như kiểm tra số chẵn lẻ, lặp theo chu kỳ hoặc xác định vị trí trong một nhóm.
Toán tử so sánh
Toán tử so sánh tạo ra kết quả boolean. Một số toán tử quan trọng gồm ===, !==, >, , >= và .
const age = 20;
console.log(age >= 18);
console.log(age === 20);
Người mới nên hình thành thói quen ưu tiên === thay cho == khi cần so sánh bằng. Toán tử === kiểm tra cả giá trị và kiểu dữ liệu, giúp hạn chế những kết quả gây bất ngờ do cơ chế chuyển đổi kiểu tự động.
Toán tử logic
Ba toán tử logic quan trọng là &&, || và !.
&& thường được dùng khi cần nhiều điều kiện cùng đúng:
const age = 25;
const hasCard = true;
if (age >= 18 && hasCard) {
console.log("Có thể tiếp tục");
}
|| thường được dùng khi chỉ cần một trong các điều kiện đúng:
const isAdmin = false;
const isEditor = true;
if (isAdmin || isEditor) {
console.log("Có quyền quản lý nội dung");
}
! đảo ngược giá trị boolean:
const isLoggedIn = false;
if (!isLoggedIn) {
console.log("Vui lòng đăng nhập");
}
Khi kết hợp các toán tử này, điều quan trọng không phải là ghi nhớ ký hiệu mà là đọc được ý nghĩa của biểu thức như một câu điều kiện thông thường.
Điều kiện giúp chương trình đưa ra quyết định
Một chương trình thực tế hiếm khi chỉ chạy theo một đường thẳng từ đầu đến cuối. Nó thường phải lựa chọn cách xử lý dựa trên dữ liệu hiện tại. Người dùng đã đăng nhập hay chưa, số lượng sản phẩm còn hàng không, mật khẩu có đủ điều kiện không hoặc một giá trị có vượt giới hạn cho phép không đều là những tình huống cần đến điều kiện.
Trong JavaScript, cấu trúc if là điểm bắt đầu để xây dựng loại logic này. Điều kiện bên trong dấu ngoặc được đánh giá và nếu kết quả là true, khối lệnh tương ứng sẽ được thực hiện.
const age = 20;
if (age >= 18) {
console.log("Đủ tuổi");
}
Cách đọc đoạn mã trên rất tự nhiên: nếu tuổi lớn hơn hoặc bằng 18 thì thực hiện hành động bên trong khối lệnh.
if, else và else if
Khi chương trình cần xử lý hai khả năng đối lập, else cho phép định nghĩa nhánh còn lại.
const age = 16;
if (age >= 18) {
console.log("Đủ tuổi");
} else {
console.log("Chưa đủ tuổi");
}
Nếu có nhiều mức điều kiện, có thể sử dụng else if.
const score = 8;
if (score >= 9) {
console.log("Xuất sắc");
} else if (score >= 7) {
console.log("Khá");
} else if (score >= 5) {
console.log("Trung bình");
} else {
console.log("Cần cải thiện");
}
Không nên tạo quá nhiều tầng if lồng nhau nếu bài toán có thể được tổ chức theo cách rõ ràng hơn. Điều kiện càng sâu thì việc đọc, kiểm thử và sửa lỗi càng khó.
Điều kiện nên mô tả một quyết định cụ thể
Một lỗi thường gặp ở người mới là viết điều kiện quá dài chỉ vì muốn xử lý tất cả trường hợp trong một lần. Khi một biểu thức chứa quá nhiều phép so sánh và toán tử logic, người đọc khó xác định chương trình thực sự đang kiểm tra điều gì.
Thay vì chỉ tập trung làm cho code ngắn, hãy ưu tiên làm cho ý nghĩa của điều kiện dễ hiểu. Có thể tách những thông tin quan trọng thành biến có tên rõ ràng trước khi đưa vào cấu trúc điều kiện.
const age = 25;
const hasPermission = true;
const canAccess = age >= 18 && hasPermission;
if (canAccess) {
console.log("Cho phép truy cập");
}
Cách viết này dài hơn một chút nhưng thể hiện rõ quyết định mà chương trình đang đưa ra.
switch khi có nhiều trường hợp cố định
switch phù hợp với những tình huống một giá trị cần được đối chiếu với nhiều trường hợp cụ thể. Nó thường dễ đọc hơn một chuỗi else if dài khi tất cả nhánh đều kiểm tra cùng một giá trị.
const role = "editor";
switch (role) {
case "admin":
console.log("Quản trị viên");
break;
case "editor":
console.log("Biên tập viên");
break;
case "user":
console.log("Người dùng");
break;
default:
console.log("Vai trò không xác định");
}
Từ khóa break có nhiệm vụ kết thúc nhánh đang thực thi. Nếu quên break trong những trường hợp thông thường, JavaScript có thể tiếp tục chạy xuống các nhánh case phía sau.
switch không phải lúc nào cũng tốt hơn if. Nếu điều kiện liên quan đến các khoảng giá trị, nhiều phép so sánh hoặc biểu thức phức tạp, if thường trực quan hơn.
Vòng lặp và cách xử lý công việc lặp lại
Vòng lặp được sử dụng khi một thao tác cần thực hiện nhiều lần. Ví dụ, chương trình cần duyệt qua danh sách sản phẩm, kiểm tra từng phần tử, tính tổng các giá trị hoặc thực hiện một hành động cho đến khi đạt điều kiện nhất định.
Nếu không có vòng lặp, lập trình viên sẽ phải viết lại cùng một nhóm câu lệnh nhiều lần. Điều đó vừa làm code dài vừa tạo ra nhiều cơ hội phát sinh lỗi.
Vòng lặp for
for thường phù hợp khi bạn biết hoặc có thể mô tả rõ quá trình khởi tạo, điều kiện tiếp tục và bước thay đổi sau mỗi lần lặp.
for (let i = 0; i < 5; i++) {
console.log(i);
}
Đoạn mã trên có ba phần chính. Biến i được khởi tạo, điều kiện i quyết định vòng lặp còn tiếp tục hay không, còn i++ làm thay đổi giá trị sau mỗi lần thực hiện.
Điểm quan trọng cần hiểu là vòng lặp không phải một phép thuật khiến chương trình “chạy nhiều lần”. Nó chỉ là cách viết có cấu trúc cho một quá trình mà nếu viết thủ công sẽ phải lặp lại cùng logic.
while khi điều kiện quyết định số lần lặp
while phù hợp khi chưa biết chính xác vòng lặp sẽ chạy bao nhiêu lần, nhưng biết điều kiện để tiếp tục.
let count = 0;
while (count < 3) {
console.log(count);
count++;
}
Một điều cực kỳ quan trọng khi sử dụng while là phải bảo đảm điều kiện có khả năng trở thành false. Nếu không, chương trình có thể rơi vào vòng lặp vô hạn.
do while khi cần chạy ít nhất một lần
do while khác while ở thứ tự kiểm tra. Khối lệnh được chạy trước, sau đó JavaScript mới kiểm tra điều kiện.
let number = 0;
do {
console.log(number);
number++;
} while (number < 3);
Điều này hữu ích trong những bài toán mà hành động ban đầu phải được thực hiện ít nhất một lần trước khi quyết định có tiếp tục hay không.
break và continue trong vòng lặp
Không phải vòng lặp nào cũng cần chạy đến khi điều kiện ban đầu kết thúc. break cho phép dừng vòng lặp ngay lập tức.
for (let i = 0; i < 10; i++) {
if (i === 5) {
break;
}
console.log(i);
}
Trong ví dụ này, vòng lặp dừng khi i đạt giá trị 5.
Ngược lại, continue bỏ qua phần còn lại của lần lặp hiện tại và chuyển sang lần tiếp theo.
for (let i = 0; i < 5; i++) {
if (i === 2) {
continue;
}
console.log(i);
}
break và continue hữu ích nhưng không nên lạm dụng. Nếu một vòng lặp có quá nhiều điểm thoát hoặc bỏ qua, logic sẽ khó theo dõi. Trong code thực tế, đôi khi việc tách một phần xử lý thành hàm riêng sẽ làm chương trình rõ ràng hơn.
Hàm giúp đóng gói một nhiệm vụ
Hàm là một trong những khái niệm quan trọng nhất của JavaScript. Nếu biến giúp đặt tên cho dữ liệu thì hàm giúp đặt tên cho một quy trình xử lý.
Thay vì viết lại cùng một nhóm câu lệnh ở nhiều vị trí, bạn có thể đóng gói chúng thành một hàm rồi gọi hàm khi cần.
function sayHello() {
console.log("Xin chào");
}
sayHello();
sayHello();
Trong ví dụ trên, sayHello là tên hàm. Phần mã nằm trong dấu ngoặc nhọn là nội dung mà hàm thực hiện. Việc gọi hàm được thực hiện bằng cách viết tên hàm kèm dấu ngoặc tròn.
Tham số giúp hàm xử lý dữ liệu khác nhau
Một hàm sẽ hữu ích hơn khi có thể nhận dữ liệu từ bên ngoài.
function sayHello(name) {
console.log(`Xin chào ${name}`);
}
sayHello("An");
sayHello("Minh");
name là tham số của hàm. Khi gọi hàm, giá trị được truyền vào sẽ trở thành dữ liệu mà hàm sử dụng.
Nhờ tham số, một hàm có thể giải quyết cùng một loại công việc cho nhiều dữ liệu khác nhau thay vì tạo nhiều hàm gần như giống hệt nhau.
return đưa kết quả ra khỏi hàm
Hàm không chỉ thực hiện hành động. Nó còn có thể tính toán và trả về kết quả bằng return.
function add(a, b) {
return a + b;
}
const result = add(10, 20);
console.log(result);
Trong trường hợp này, hàm add nhận hai giá trị, thực hiện phép cộng rồi trả kết quả cho nơi gọi hàm.
Đây là một bước tiến quan trọng trong tư duy lập trình. Thay vì chỉ nghĩ rằng “hàm này làm gì”, hãy bắt đầu nghĩ thêm rằng “hàm này nhận dữ liệu gì và tạo ra kết quả gì”. Một hàm có đầu vào và đầu ra rõ ràng thường dễ kiểm thử và tái sử dụng.
Function expression và arrow function
Ngoài cách khai báo hàm truyền thống, JavaScript còn cho phép lưu một hàm vào biến.
const add = function(a, b) {
return a + b;
};
console.log(add(5, 7));
JavaScript hiện đại còn cung cấp cú pháp arrow function giúp viết những hàm ngắn gọn hơn.
const add = (a, b) => {
return a + b;
};
Nếu hàm chỉ có một biểu thức trả về kết quả, có thể viết ngắn hơn:
const add = (a, b) => a + b;
Arrow function xuất hiện rất thường xuyên trong JavaScript hiện đại, đặc biệt khi làm việc với array, callback, Promise và nhiều API khác. Tuy nhiên, người mới không nên chỉ học cú pháp rút gọn mà bỏ qua bản chất của hàm. Trước hết cần hiểu rõ tham số, giá trị trả về và phạm vi hoạt động của hàm.
Phạm vi biến và lý do let, const quan trọng
Phạm vi biến, thường gọi là scope, xác định nơi một biến có thể được truy cập. Đây là khái niệm rất dễ bị xem nhẹ khi mới học, nhưng lại là nguyên nhân của nhiều lỗi khó tìm khi chương trình lớn hơn.
Với let và const, biến được khai báo trong một block chỉ có thể được sử dụng trong phạm vi phù hợp của block đó.
if (true) {
let message = "Xin chào";
console.log(message);
}
Biến message thuộc phạm vi của block chứa nó. Việc giới hạn phạm vi giúp tránh tình trạng một biến vô tình ảnh hưởng đến những phần khác của chương trình.
Scope của hàm
Biến được khai báo bên trong hàm thường chỉ có thể được sử dụng trong phạm vi mà hàm đó kiểm soát.
function calculate() {
const price = 100000;
console.log(price);
}
calculate();
Việc đóng gói dữ liệu trong phạm vi cần thiết giúp giảm sự phụ thuộc giữa các phần của chương trình. Khi mỗi hàm quản lý được dữ liệu của chính nó, code thường dễ hiểu hơn.
Giá trị nguyên thủy và dữ liệu phức tạp
Đến đây, người mới cần bắt đầu phân biệt hai nhóm dữ liệu có cách sử dụng khác nhau. Một nhóm gồm những giá trị nguyên thủy như string, number, boolean, undefined và null. Nhóm còn lại bao gồm các cấu trúc dữ liệu như object và array.
Sự khác biệt này trở nên quan trọng khi bạn gán dữ liệu cho biến, truyền dữ liệu vào hàm hoặc thay đổi dữ liệu trong chương trình.
Object dùng để mô tả một thực thể
Object cho phép gom nhiều thuộc tính liên quan vào cùng một cấu trúc.
const user = {
name: "An",
age: 25,
isActive: true
};
Thay vì tạo ba biến rời rạc, object cho phép mô tả một người dùng bằng một cấu trúc thống nhất.
Có thể truy cập thuộc tính bằng dấu chấm:
console.log(user.name);
console.log(user.age);
Object là nền tảng quan trọng vì dữ liệu trong ứng dụng thực tế thường có nhiều thuộc tính liên quan. Khi làm việc với API, cơ sở dữ liệu hoặc dữ liệu biểu mẫu, bạn sẽ liên tục gặp những cấu trúc tương tự.
Array dùng để quản lý một danh sách
Array phù hợp khi cần lưu nhiều giá trị theo thứ tự.
const fruits = ["Táo", "Cam", "Xoài"];
console.log(fruits[0]);
console.log(fruits[1]);
Chỉ số của array bắt đầu từ 0, vì vậy phần tử đầu tiên nằm ở vị trí 0 chứ không phải 1.
Array có thể chứa nhiều kiểu dữ liệu, nhưng trong chương trình thực tế nên ưu tiên những danh sách có cấu trúc rõ ràng.
const users = [
{
name: "An",
age: 25
},
{
name: "Minh",
age: 30
}
];
Đây là kiểu cấu trúc rất phổ biến: một array chứa nhiều object. Việc hiểu chắc mô hình này sẽ giúp người học dễ tiếp cận dữ liệu JSON và API ở những phần nâng cao hơn.
Làm việc với object trong chương trình thực tế
Object không chỉ dùng để lưu dữ liệu. Nó còn giúp chương trình biểu diễn những đối tượng có nhiều đặc điểm liên quan với nhau. Khi xây dựng website, bạn có thể gặp object đại diện cho người dùng, sản phẩm, bài viết, đơn hàng hoặc cấu hình của một thành phần giao diện.
Thuộc tính của object có thể được đọc, thay đổi hoặc bổ sung khi chương trình chạy.
const user = {
name: "An",
age: 25
};
user.age = 26;
user.email = "an@example.com";
console.log(user);
Ở đây, thuộc tính age được cập nhật và thuộc tính email được bổ sung sau khi object được tạo.
Truy cập thuộc tính bằng dấu ngoặc vuông
Ngoài dấu chấm, JavaScript còn cho phép truy cập thuộc tính bằng dấu ngoặc vuông. Cách này đặc biệt hữu ích khi tên thuộc tính được lưu trong một biến.
const user = {
name: "An",
age: 25
};
const property = "name";
console.log(user[property]);
Điểm khác biệt quan trọng là user.name tìm thuộc tính có tên chính xác là name, trong khi user[property] sử dụng giá trị hiện tại của biến property để xác định thuộc tính cần truy cập.
Đây là kỹ thuật thường xuất hiện khi xử lý dữ liệu động, biểu mẫu hoặc các cấu trúc được tạo dựa trên dữ liệu từ máy chủ.
Các thao tác quan trọng với array
Array xuất hiện rất thường xuyên trong JavaScript. Tuy nhiên, thay vì chỉ biết truy cập phần tử bằng chỉ số, người mới nên sớm làm quen với những phương thức giúp tìm kiếm, biến đổi và lọc danh sách.
Thêm và xóa phần tử
push() thêm phần tử vào cuối array.
const numbers = [1, 2, 3];
numbers.push(4);
console.log(numbers);
pop() loại bỏ phần tử cuối cùng.
const numbers = [1, 2, 3];
numbers.pop();
console.log(numbers);
Ở phía đầu array, unshift() thêm phần tử và shift() loại bỏ phần tử đầu tiên.
const numbers = [2, 3];
numbers.unshift(1);
console.log(numbers);
numbers.shift();
console.log(numbers);
Các phương thức này thay đổi trực tiếp array ban đầu. Đây là điều cần ghi nhớ khi một array đang được nhiều phần của chương trình cùng sử dụng.
map tạo ra một danh sách mới
map() được sử dụng khi cần biến đổi từng phần tử trong array để tạo ra một array khác.
const prices = [100, 200, 300];
const newPrices = prices.map(price => price * 2);
console.log(newPrices);
Trong trường hợp này, mỗi giá trị được nhân với 2 và kết quả được đưa vào một array mới. map() rất hữu ích khi dữ liệu cần chuyển từ dạng này sang dạng khác.
Ví dụ, với danh sách object:
const users = [
{ name: "An", age: 25 },
{ name: "Minh", age: 30 }
];
const names = users.map(user => user.name);
console.log(names);
Kết quả là một danh sách chỉ chứa tên. Đây là cách xử lý dữ liệu phổ biến hơn nhiều so với việc viết vòng lặp thủ công cho mọi tình huống.
filter dùng để lọc dữ liệu
filter() tạo ra một array mới chỉ chứa những phần tử thỏa mãn điều kiện.
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(evenNumbers);
Với dữ liệu object, cách dùng cũng tương tự:
const users = [
{ name: "An", age: 17 },
{ name: "Minh", age: 25 },
{ name: "Lan", age: 30 }
];
const adults = users.filter(user => user.age >= 18);
console.log(adults);
map() và filter() là hai phương thức người học JavaScript nên hiểu thật chắc. Chúng xuất hiện liên tục khi xử lý danh sách dữ liệu trong ứng dụng web.
find tìm phần tử phù hợp
Nếu mục tiêu là tìm một phần tử đầu tiên thỏa mãn điều kiện, find() thường phù hợp hơn filter().
const users = [
{ id: 1, name: "An" },
{ id: 2, name: "Minh" },
{ id: 3, name: "Lan" }
];
const user = users.find(user => user.id === 2);
console.log(user);
Nếu không tìm thấy phần tử phù hợp, find() trả về undefined. Vì vậy, code sử dụng kết quả của find() cần tính đến trường hợp không có dữ liệu.
forEach để thực hiện hành động trên từng phần tử
forEach() cho phép chạy một hàm đối với từng phần tử trong array.
const names = ["An", "Minh", "Lan"];
names.forEach(name => {
console.log(name);
});
forEach() phù hợp khi bạn muốn thực hiện một hành động cho từng phần tử nhưng không cần tạo ra một array kết quả mới. Nếu cần biến đổi dữ liệu thành array khác, map() thường thể hiện đúng mục đích hơn.
Callback function là gì?
Callback là một khái niệm quan trọng vì nó xuất hiện trong rất nhiều API của JavaScript. Hiểu đơn giản, callback là một hàm được truyền vào một hàm khác để được gọi tại thời điểm phù hợp.
function processUser(name, callback) {
console.log(`Đang xử lý ${name}`);
callback();
}
processUser("An", function() {
console.log("Đã xử lý xong");
});
Trong ví dụ này, hàm được truyền vào processUser() chính là callback.
Các phương thức như map(), filter() và forEach() đều sử dụng callback. Khi hiểu callback, cách hoạt động của những phương thức này sẽ trở nên dễ hiểu hơn.
Destructuring giúp lấy dữ liệu ngắn gọn
Khi làm việc với object và array, bạn thường xuyên cần lấy một hoặc nhiều giá trị ra để sử dụng. Destructuring cung cấp cú pháp ngắn gọn cho việc này.
Destructuring object
const user = {
name: "An",
age: 25
};
const { name, age } = user;
console.log(name);
console.log(age);
Thay vì phải viết từng câu lệnh truy cập thuộc tính, destructuring cho phép lấy các thuộc tính cần thiết ngay trong lúc khai báo biến.
Destructuring array
const colors = ["red", "green", "blue"];
const [first, second, third] = colors;
console.log(first);
console.log(second);
console.log(third);
Với array, giá trị được lấy dựa trên vị trí. Với object, giá trị được lấy dựa trên tên thuộc tính.
DOM là cầu nối giữa JavaScript và giao diện
Đến đây, JavaScript vẫn mới chủ yếu xử lý dữ liệu trong bộ nhớ. Để tạo ra tương tác thực sự trên trang web, JavaScript cần làm việc với cấu trúc HTML hiện tại. Đây là lúc DOM xuất hiện.
DOM, viết đầy đủ là Document Object Model, là mô hình mà trình duyệt xây dựng từ tài liệu HTML để JavaScript có thể truy cập và thao tác với các phần tử trên trang.
Ví dụ, nếu trang có một phần tử mang định danh title, JavaScript có thể tìm phần tử đó và thay đổi nội dung.
const title = document.getElementById("title");
title.textContent = "Nội dung mới";
Đây là bước rất quan trọng trong quá trình học JavaScript web. Bạn chuyển từ việc “tính toán trong chương trình” sang việc “dùng chương trình để thay đổi giao diện”.
querySelector
querySelector() cho phép tìm phần tử dựa trên CSS selector.
const title = document.querySelector("#title");
Có thể tìm phần tử theo class:
const box = document.querySelector(".box");
Hoặc theo tên phần tử:
const paragraph = document.querySelector("p");
querySelector() trả về phần tử đầu tiên phù hợp với selector. Khi cần lấy nhiều phần tử, có thể sử dụng querySelectorAll().
const items = document.querySelectorAll(".item");
DOM API rất rộng, vì vậy người mới không cần cố ghi nhớ tất cả phương thức ngay lập tức. Quan trọng nhất là hiểu quy trình: tìm phần tử → đọc dữ liệu → thay đổi dữ liệu hoặc thuộc tính → giao diện được cập nhật.
Xử lý sự kiện trong trình duyệt
Website tương tác dựa rất nhiều vào sự kiện. Người dùng có thể nhấp chuột, nhập bàn phím, gửi biểu mẫu, di chuyển chuột hoặc thay đổi lựa chọn. JavaScript có thể lắng nghe những sự kiện này và thực hiện logic tương ứng.
click event
Ví dụ, một nút có thể được xử lý bằng addEventListener():
const button = document.querySelector("#button");
button.addEventListener("click", function() {
console.log("Đã nhấp nút");
});
Cách này tách hành động của người dùng khỏi phần logic xử lý. Khi sự kiện click xảy ra, callback được truyền vào addEventListener() sẽ được gọi.
Thay đổi nội dung giao diện
JavaScript có thể cập nhật nội dung của phần tử thông qua textContent.
const button = document.querySelector("#button");
const message = document.querySelector("#message");
button.addEventListener("click", function() {
message.textContent = "Bạn vừa nhấp vào nút";
});
Đây là nền tảng của rất nhiều thành phần giao diện như thông báo, tab, bộ lọc, menu, bộ đếm và trạng thái hiển thị.
Lấy dữ liệu từ biểu mẫu
Biểu mẫu là một trong những nơi JavaScript được sử dụng nhiều nhất. Người dùng nhập thông tin, JavaScript đọc dữ liệu, kiểm tra điều kiện rồi quyết định có cho phép gửi hay không.
Ví dụ, có thể lấy nội dung từ một ô nhập liệu:
const input = document.querySelector("#name");
const name = input.value;
console.log(name);
Giá trị từ biểu mẫu thường bắt đầu dưới dạng chuỗi. Vì vậy, nếu người dùng nhập một con số và bạn muốn thực hiện phép tính, cần xử lý kiểu dữ liệu phù hợp thay vì mặc nhiên coi dữ liệu nhập vào là number.
Ngăn biểu mẫu gửi dữ liệu mặc định
Khi một biểu mẫu được gửi, trình duyệt có hành vi mặc định. Trong những ứng dụng cần xử lý dữ liệu bằng JavaScript trước, bạn có thể sử dụng preventDefault().
const form = document.querySelector("#form");
form.addEventListener("submit", function(event) {
event.preventDefault();
console.log("Đã xử lý biểu mẫu bằng JavaScript");
});
Cách tiếp cận này là nền tảng cho các biểu mẫu có kiểm tra dữ liệu phía trình duyệt, gửi dữ liệu bằng API hoặc hiển thị lỗi mà không cần tải lại toàn bộ trang.
Kiểm tra dữ liệu trước khi xử lý
Một chương trình tốt không nên giả định rằng dữ liệu đầu vào luôn chính xác. Người dùng có thể bỏ trống trường bắt buộc, nhập sai định dạng hoặc cung cấp giá trị nằm ngoài giới hạn cho phép.
Ví dụ:
const name = "";
if (name.trim() === "") {
console.log("Vui lòng nhập tên");
}
Phương thức trim() loại bỏ khoảng trắng ở đầu và cuối chuỗi. Điều này giúp tránh trường hợp người dùng chỉ nhập khoảng trắng nhưng chương trình vẫn xem đó là dữ liệu hợp lệ.
Việc kiểm tra dữ liệu ở phía trình duyệt giúp cải thiện trải nghiệm người dùng, nhưng không nên được xem là lớp bảo vệ duy nhất. Khi dữ liệu được gửi đến máy chủ, phía máy chủ vẫn cần tự kiểm tra lại.
Comment và cách ghi chú mã nguồn
Comment cho phép thêm ghi chú vào code mà JavaScript không thực thi như một phần của chương trình.
// Đây là một comment một dòng
const price = 100000;
Với nhiều dòng:
/*
Đây là comment
gồm nhiều dòng
*/
Comment hữu ích khi giải thích lý do của một đoạn xử lý hoặc một quyết định kỹ thuật khó nhận biết chỉ bằng cách đọc code. Tuy nhiên, không nên dùng comment để giải thích những câu lệnh vốn đã quá rõ ràng.
Một nguyên tắc tốt là trước tiên đặt tên biến và hàm đủ rõ nghĩa. Khi code tự giải thích được phần lớn ý định của nó, số lượng comment cần thiết cũng giảm xuống.
Hiểu lỗi để sửa JavaScript đúng cách
Lỗi là một phần bình thường của quá trình lập trình. Người mới thường nghĩ rằng lập trình viên giỏi là người viết code không bao giờ gặp lỗi, nhưng thực tế khác hoàn toàn. Điểm khác biệt nằm ở khả năng đọc lỗi, xác định nguyên nhân và sửa đúng vấn đề thay vì sửa một cách ngẫu nhiên.
Khi JavaScript gặp lỗi nghiêm trọng trong quá trình thực thi, chương trình có thể dừng tại vị trí phát sinh lỗi. Console của trình duyệt thường cung cấp thông tin quan trọng như loại lỗi, thông báo và vị trí tương đối trong mã nguồn.
Lỗi cú pháp
Lỗi cú pháp xảy ra khi mã JavaScript không tuân theo cấu trúc mà ngôn ngữ yêu cầu.
if (true {
console.log("Hello");
}
Trong ví dụ này, dấu ngoặc đóng của điều kiện bị thiếu. JavaScript không thể phân tích đoạn mã thành cấu trúc hợp lệ nên chương trình không thể thực thi đoạn mã đó như mong muốn.
Với loại lỗi này, hãy kiểm tra dấu ngoặc tròn, dấu ngoặc nhọn, dấu ngoặc vuông, chuỗi ký tự và cấu trúc câu lệnh trước tiên.
Lỗi tham chiếu
Lỗi tham chiếu thường xảy ra khi chương trình cố sử dụng một biến hoặc tên không tồn tại trong phạm vi hiện tại.
console.log(userName);
Nếu userName chưa được khai báo hoặc không thể truy cập tại vị trí đó, JavaScript có thể phát sinh lỗi tham chiếu.
Đây là lý do hiểu scope quan trọng. Khi gặp lỗi kiểu này, hãy kiểm tra biến được khai báo ở đâu, tên có chính xác không và vị trí đang sử dụng có nằm trong phạm vi cho phép hay không.
Lỗi logic khó nhận biết hơn lỗi cú pháp
Có những chương trình chạy bình thường nhưng cho kết quả sai. Đây là lỗi logic. JavaScript không thể tự biết rằng kết quả mà bạn mong muốn khác với kết quả mà code đang yêu cầu nó tạo ra.
const price = 100;
const quantity = 2;
const total = price + quantity;
console.log(total);
Đoạn mã không nhất thiết gây lỗi cú pháp, nhưng nếu mục tiêu là tính tổng tiền thì phép tính phải là phép nhân. Đây là ví dụ đơn giản cho thấy chương trình có thể “chạy được” nhưng vẫn sai.
Khi debug lỗi logic, hãy kiểm tra dữ liệu đầu vào, từng bước biến đổi dữ liệu và kết quả trung gian thay vì chỉ nhìn vào dòng cuối cùng.
Console là công cụ quan trọng khi học JavaScript
Console không chỉ dùng để in ra một dòng chữ. Nó là công cụ giúp quan sát trạng thái của chương trình trong quá trình chạy.
const price = 150000;
const quantity = 3;
const total = price * quantity;
console.log("price:", price);
console.log("quantity:", quantity);
console.log("total:", total);
Khi một kết quả không đúng, việc in các giá trị trung gian có thể giúp xác định chính xác bước nào bắt đầu cho ra dữ liệu sai.
Người mới nên hình thành thói quen kiểm tra giả thuyết bằng console thay vì đoán. Nếu bạn nghĩ một biến có giá trị nào đó, hãy kiểm tra nó. Nếu nghĩ một điều kiện trả về true, hãy kiểm tra kết quả. Debug hiệu quả bắt đầu từ việc biến một vấn đề mơ hồ thành một vấn đề có thể quan sát.
JSON và dữ liệu trao đổi giữa trình duyệt với máy chủ
Khi website bắt đầu làm việc với dữ liệu từ máy chủ, JSON là một định dạng mà bạn sẽ gặp thường xuyên. JSON có cấu trúc gần với object và array của JavaScript nên khá dễ tiếp cận với người mới.
{
"name": "An",
"age": 25,
"active": true
}
JSON là dữ liệu dạng văn bản theo một quy tắc cụ thể. Nó không phải hoàn toàn đồng nghĩa với JavaScript object, dù hình thức của chúng có nhiều điểm tương đồng.
Chuyển JSON thành dữ liệu JavaScript
JavaScript cung cấp JSON.parse() để chuyển một chuỗi JSON thành giá trị JavaScript.
const json = '{"name":"An","age":25}';
const user = JSON.parse(json);
console.log(user.name);
Chuyển dữ liệu JavaScript thành JSON
Chiều ngược lại được thực hiện bằng JSON.stringify().
const user = {
name: "An",
age: 25
};
const json = JSON.stringify(user);
console.log(json);
Hai phương thức này là nền tảng khi bạn bắt đầu gửi và nhận dữ liệu giữa JavaScript với API.
Lập trình bất đồng bộ và lý do JavaScript không chờ mọi thứ
Một website có thể phải chờ máy chủ trả dữ liệu, chờ bộ hẹn giờ hoàn thành hoặc chờ một thao tác bên ngoài kết thúc. Nếu trình duyệt phải đứng yên chờ từng công việc như vậy, giao diện sẽ rất khó sử dụng.
JavaScript vì thế có cơ chế hỗ trợ xử lý những công việc không hoàn thành ngay lập tức. Đây là nhóm kiến thức thường khiến người mới bối rối vì chương trình không phải lúc nào cũng chạy theo cách “dòng trên xong rồi mới đến dòng dưới” như cách hình dung đơn giản ban đầu.
setTimeout
Một ví dụ dễ quan sát là setTimeout().
console.log("Bắt đầu");
setTimeout(function() {
console.log("Đã chờ");
}, 2000);
console.log("Kết thúc");
Điểm đáng chú ý là thông báo “Kết thúc” có thể xuất hiện trước thông báo bên trong setTimeout(). Điều này cho thấy việc đăng ký một công việc chờ không đồng nghĩa với việc JavaScript dừng toàn bộ chương trình tại đó.
Hiểu được ý tưởng này sẽ giúp bạn dễ tiếp cận Promise và async/await hơn.
Promise và cách biểu diễn một công việc chưa hoàn thành
Promise có thể được hiểu là một đại diện cho kết quả của một công việc bất đồng bộ. Tại thời điểm tạo ra Promise, kết quả có thể chưa có. Sau đó, công việc có thể hoàn thành thành công hoặc thất bại.
Một Promise có thể được xử lý bằng then() và catch().
const promise = new Promise(function(resolve, reject) {
const success = true;
if (success) {
resolve("Thành công");
} else {
reject("Có lỗi xảy ra");
}
});
promise
.then(function(result) {
console.log(result);
})
.catch(function(error) {
console.log(error);
});
Người mới không cần học thuộc cấu trúc này ngay lập tức. Điều cần hiểu trước là Promise mô tả một công việc có thể hoàn thành trong tương lai và có thể dẫn đến hai hướng chính: thành công hoặc thất bại.
async và await giúp đọc code bất đồng bộ dễ hơn
async và await cung cấp cách viết thuận tiện hơn khi làm việc với Promise. Mục tiêu lớn nhất là làm cho luồng xử lý dễ đọc hơn.
async function loadData() {
const result = await getData();
console.log(result);
}
Từ khóa await thường được sử dụng bên trong hàm async. Nó khiến luồng xử lý của hàm chờ Promise hoàn thành trước khi tiếp tục các câu lệnh tiếp theo trong hàm đó.
Điều này không có nghĩa toàn bộ trình duyệt bị đóng băng. Chỉ luồng xử lý liên quan đến hàm đang chờ bị tạm dừng ở điểm đó, trong khi môi trường JavaScript vẫn có thể tiếp tục xử lý những công việc khác.
Xử lý lỗi với try và catch
Khi sử dụng async/await, try...catch thường được dùng để xử lý lỗi.
async function loadData() {
try {
const result = await getData();
console.log(result);
} catch (error) {
console.log("Không thể tải dữ liệu");
}
}
Cách tổ chức này giúp tách phần xử lý thành công khỏi phần xử lý thất bại, đặc biệt hữu ích khi làm việc với API.
Gọi API bằng fetch
fetch() là một API phổ biến của trình duyệt để thực hiện các yêu cầu mạng. Đây là bước chuyển quan trọng từ một trang web chủ yếu xử lý dữ liệu cục bộ sang một ứng dụng có thể giao tiếp với máy chủ.
fetch("/api/users")
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.log(error);
});
Quá trình trên có thể hiểu theo các bước: gửi yêu cầu đến địa chỉ, nhận phản hồi, chuyển nội dung phản hồi thành dữ liệu JavaScript rồi xử lý dữ liệu.
Với async/await, cùng ý tưởng có thể được viết theo cách dễ đọc hơn:
async function loadUsers() {
try {
const response = await fetch("/api/users");
const data = await response.json();
console.log(data);
} catch (error) {
console.log(error);
}
}
Đây là một trong những kỹ năng quan trọng mà người học JavaScript cần đạt được trước khi chuyển sang các ứng dụng web phức tạp hơn.
Module giúp chia chương trình thành nhiều phần
Khi ứng dụng nhỏ, bạn có thể đặt nhiều hàm và biến trong một tệp. Nhưng khi chương trình phát triển, một tệp JavaScript quá lớn sẽ trở nên khó đọc và khó bảo trì.
Module cho phép chia chương trình thành những phần có trách nhiệm tương đối rõ ràng. Một module có thể cung cấp một số hàm hoặc dữ liệu để module khác sử dụng.
export và import
Ví dụ một tệp có thể export một hàm:
export function add(a, b) {
return a + b;
}
Tệp khác có thể import hàm đó:
import { add } from "./math.js";
console.log(add(10, 20));
Cách tổ chức này giúp giảm sự phụ thuộc vào một tệp duy nhất. Khi dự án lớn hơn, việc chia code theo chức năng sẽ giúp tìm và sửa vấn đề dễ dàng hơn.
Những kiến thức người mới không nên học theo kiểu thuộc lòng
JavaScript có rất nhiều phương thức và cú pháp. Nếu cố ghi nhớ toàn bộ ngay từ đầu, bạn rất dễ bị quá tải và sau đó vẫn không biết áp dụng vào bài toán thực tế.
Thay vào đó, hãy ưu tiên hiểu các nguyên lý:
- Dữ liệu được lưu và thay đổi như thế nào.
- Điều kiện quyết định chương trình đi theo hướng nào.
- Vòng lặp xử lý một tập dữ liệu ra sao.
- Hàm nhận đầu vào và tạo ra kết quả như thế nào.
- Object và array dùng để mô hình hóa dữ liệu ra sao.
- DOM kết nối JavaScript với giao diện như thế nào.
- Sự kiện khiến code được thực thi tại thời điểm nào.
- Promise và async/await giải quyết công việc bất đồng bộ ra sao.
- Module giúp tổ chức mã nguồn như thế nào.
Khi những nền tảng này chắc, việc tra cứu một phương thức mới không còn đáng sợ. Bạn chỉ cần biết mình đang muốn giải quyết loại vấn đề nào, sau đó tìm API phù hợp.
Những lỗi học JavaScript thường gặp ở người mới
Chỉ xem bài học mà không tự viết code
Xem một đoạn code chạy đúng tạo ra cảm giác rằng mình đã hiểu. Nhưng khả năng nhận biết code và khả năng tự xây dựng code là hai kỹ năng khác nhau.
Sau mỗi khái niệm, hãy tự viết lại từ đầu mà không nhìn lời giải. Nếu có thể thay đổi dữ liệu, thêm điều kiện và biến đổi ví dụ thành một bài toán khác, kiến thức mới thực sự bắt đầu trở thành kỹ năng.
Học thuộc cú pháp nhưng không giải bài toán
Nhớ cú pháp for không có nghĩa là biết khi nào nên dùng vòng lặp. Nhớ map() cũng không có nghĩa là hiểu khi nào cần biến đổi một danh sách.
Hãy bắt đầu từ yêu cầu: dữ liệu đầu vào là gì, kết quả mong muốn là gì và cần những bước xử lý nào để đi từ đầu vào đến đầu ra. Sau đó mới chọn cú pháp.
Nhảy quá sớm vào framework
Các framework và thư viện hiện đại rất hữu ích, nhưng chúng không thay thế kiến thức JavaScript. Nếu chưa hiểu biến, hàm, object, array, scope, callback, Promise và module, việc học framework có thể trở thành quá trình học thuộc cách viết mà không hiểu nguyên lý bên dưới.
Nền tảng JavaScript càng chắc, bạn càng dễ chuyển giữa các công cụ khác nhau mà không phải học lại từ đầu.
Lộ trình thực hành JavaScript cho người mới
Thay vì học tất cả kiến thức cùng một lúc, người mới có thể chia quá trình thành những giai đoạn nhỏ. Mỗi giai đoạn nên đi kèm bài tập và một sản phẩm thực tế.
Giai đoạn đầu: làm chủ nền tảng ngôn ngữ
Hãy tập trung vào biến, kiểu dữ liệu, toán tử, điều kiện, vòng lặp và hàm. Các bài tập nên đơn giản nhưng yêu cầu bạn tự suy nghĩ.
- Tính tổng và trung bình của một danh sách số.
- Kiểm tra một số có phải số chẵn hay không.
- Tìm giá trị lớn nhất trong một array.
- Lọc những phần tử thỏa mãn một điều kiện.
- Tạo hàm tính giá trị dựa trên nhiều tham số.
Mục tiêu của giai đoạn này không phải tạo giao diện đẹp mà là rèn khả năng biến yêu cầu thành thuật toán.
Giai đoạn tiếp theo: xử lý dữ liệu
Sau khi nắm được nền tảng, hãy chuyển sang object, array và các phương thức như map(), filter(), find(), forEach(). Đây là lúc các bài tập nên gần với dữ liệu thực tế hơn.
Ví dụ, bạn có thể tạo danh sách sản phẩm rồi thực hiện các thao tác như lọc theo giá, tìm sản phẩm theo mã, tính tổng tiền hoặc tạo một danh sách chỉ chứa tên sản phẩm.
Tiếp theo: kết nối JavaScript với giao diện
Hãy học DOM và event bằng những dự án nhỏ như bộ đếm, tab nội dung, menu mở rộng, danh sách công việc hoặc biểu mẫu kiểm tra dữ liệu.
Mỗi dự án nên yêu cầu bạn xử lý ít nhất ba thành phần: dữ liệu, sự kiện và thay đổi giao diện. Khi đó bạn bắt đầu nhìn thấy vai trò thực tế của JavaScript thay vì chỉ học cú pháp riêng lẻ.
Cuối cùng: bất đồng bộ và API
Sau khi đã quen với JavaScript phía trình duyệt, hãy học Promise, async/await, fetch và JSON. Bạn có thể xây dựng một trang lấy dữ liệu từ API rồi hiển thị, lọc hoặc tìm kiếm dữ liệu đó.
Đây là giai đoạn rất quan trọng vì nó giúp bạn hiểu cách một ứng dụng web thực sự giao tiếp với hệ thống phía máy chủ.
Học JavaScript thế nào để tiến bộ nhanh hơn?
Cách học hiệu quả không phải là cố hoàn thành thật nhiều bài học trong thời gian ngắn. Quan trọng hơn là khả năng tự giải quyết vấn đề mà không cần nhìn lời giải ngay lập tức.
Một quy trình thực hành tốt có thể bắt đầu bằng việc đọc yêu cầu, xác định dữ liệu đầu vào, mô tả kết quả mong muốn, chia bài toán thành các bước nhỏ rồi mới viết code.
Khi code không chạy, đừng lập tức xóa toàn bộ và viết lại. Hãy tìm vị trí đầu tiên mà kết quả bắt đầu khác với mong đợi. Sau đó kiểm tra giá trị tại điểm đó bằng console hoặc debugger.
Đặc biệt, hãy tập thói quen đọc tài liệu. Không ai nhớ được toàn bộ API của JavaScript. Lập trình viên thực tế thường xuyên tra cứu cú pháp, tham số và hành vi của phương thức. Khả năng tìm đúng thông tin và áp dụng nó quan trọng hơn việc cố nhớ mọi thứ.
Từ JavaScript cơ bản đến phát triển web thực tế
JavaScript cơ bản không phải một đích đến riêng biệt mà là nền móng cho những kiến thức phía sau. Khi đã hiểu chắc biến, kiểu dữ liệu, điều kiện, vòng lặp, hàm, object, array, scope, DOM, event, Promise và module, bạn có thể tiếp tục đi sâu vào những chủ đề phức tạp hơn.
Hướng học tiếp theo có thể bao gồm DOM nâng cao, xử lý biểu mẫu, Web Storage, module hiện đại, xử lý API, lập trình bất đồng bộ, class, prototype, quản lý trạng thái và các công cụ xây dựng dự án.
Sau đó, nếu mục tiêu là phát triển ứng dụng web hiện đại, bạn có thể tiếp cận các thư viện hoặc framework JavaScript. Lúc này, framework nên được xem là công cụ giúp tổ chức và xây dựng ứng dụng, thay vì trở thành thứ phải học thay cho ngôn ngữ nền tảng.
JavaScript cơ bản cần đạt đến mức nào trước khi học nâng cao?
Bạn không cần biết toàn bộ JavaScript mới được phép chuyển sang kiến thức nâng cao. Một dấu hiệu tốt là bạn có thể tự đọc một yêu cầu đơn giản, xác định dữ liệu cần xử lý, chia bài toán thành các hàm và viết chương trình mà không phải sao chép nguyên mẫu từ một bài hướng dẫn.
Bạn cũng nên đủ tự tin để đọc lỗi trong console, kiểm tra giá trị biến, làm việc với array và object, xử lý sự kiện DOM, viết hàm bất đồng bộ và nhận dữ liệu JSON từ một API đơn giản.
Nếu vẫn phải ghi nhớ từng dòng code để thực hiện những thao tác cơ bản, hãy dành thêm thời gian luyện tập trước khi chuyển sang framework. Ngược lại, nếu bạn đã có thể tự xây dựng những dự án nhỏ và giải thích được vì sao code hoạt động, bạn đã có nền tảng tốt để đi tiếp.
Kết luận
JavaScript trở nên dễ học hơn khi bạn không xem nó là một danh sách cú pháp phải ghi nhớ. Hãy nhìn nó như một công cụ để mô tả dữ liệu, xử lý thông tin, đưa ra quyết định và phản hồi lại hành động của người dùng.
Người mới nên xây nền tảng theo thứ tự hợp lý: biến và kiểu dữ liệu, toán tử, điều kiện, vòng lặp, hàm, object, array, scope, DOM, sự kiện, xử lý lỗi, JSON, bất đồng bộ, API và module. Mỗi kiến thức nên được củng cố bằng bài tập hoặc một tính năng nhỏ thay vì chỉ đọc lý thuyết.
Khi đã hiểu cách JavaScript suy nghĩ và vận hành, việc học những công cụ hiện đại phía trên sẽ nhẹ nhàng hơn rất nhiều. Đó cũng là nền tảng để bạn chuyển từ việc viết những đoạn mã thử nghiệm sang xây dựng các website và ứng dụng web có cấu trúc rõ ràng, dễ bảo trì và có khả năng mở rộng.
Web Mới định hướng việc học và phát triển web theo hướng hiểu bản chất thay vì phụ thuộc máy móc vào công cụ. Với JavaScript, nền tảng vững không chỉ giúp bạn viết được code chạy đúng mà còn giúp bạn biết cách tổ chức logic, phát hiện vấn đề và đưa ra giải pháp phù hợp khi dự án thực tế trở nên phức tạp.
- 0 Bình luận
Email, Điện thoại của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *