Vũ khí thứ ba // 동작
Trang đã đẹp. Nhưng bấm nút — chẳng có gì xảy ra.
세 번째 무기 — 동작
Chạm nửa phải màn hình để lật trang ›
Tóm tắt hai chương trước
Mới cầm cuốn này lên từ Chương 03? Đây là tất cả những gì bạn cần biết:
● Một hệ thống bị tấn công. Website công ty NOX TECH biến mất lúc 02:44 sáng. Kẻ gây ra ký tên lạnh người: "A." — và hắn dùng AI để đánh nhanh hơn con người.
● Một người chưa biết gì được kéo vào. Linh — mật danh ZERO, du học sinh Việt tại Hàn — chưa từng viết một dòng code, trở thành mảnh ghép cuối của đội, với deadline 72 giờ.
● Chương 01 — HTML: ZERO dựng "bộ khung" trang web đầu tiên. Chương 02 — CSS: cô khoác cho nó lớp áo, biến trang "như từ năm 1995" thành chuyên nghiệp.
● Nhưng trang vẫn "chết". Đẹp, gọn, co giãn trên mọi màn hình — mà bấm vào chẳng có gì xảy ra. Một trang web không phản hồi chỉ là tấm ảnh đẹp. Còn "A." thì tấn công bằng thứ biết hành động.
Bạn đang ở đây — chặng 3 / 7
03
세 번째 무기 — 동작
— Trang đã đẹp. Khách quay lại. Rồi một lời phàn nàn mới xuất hiện. —
Đó là cách web hoạt động: trình duyệt hỏi, máy chủ đáp. Nhưng khi trang đã nằm trong trình duyệt — thứ làm nó biết phản ứng với từng cú bấm, cú gõ của bạn lại là một vũ khí khác: JavaScript.
Phản hồi người dùng · dồn dập
Trang thông báo giờ đã tươm tất, có màu, có bố cục. Trưởng nhóm vừa thở phào thì một tin nhắn từ bộ phận chăm sóc khách hàng nhảy lên: hàng loạt người dùng bấm nút "Nhận thông báo khi sửa xong" — nhưng chẳng có gì xảy ra cả. Nút bấm như một cái xác. Và đúng khoảnh khắc đó, một góc màn hình lóe lên dòng chữ đỏ.
Một trang không chuyển động chỉ là một cái xác. Thứ các ngươi tạo ra chỉ là một cỗ quan tài đẹp đẽ. Cái nút kia ư? Nó sẽ không bao giờ hoạt động.
— THE BUGTiền bối chỉ mỉm cười. "Trang không hỏng. Nó điếc — em đang nói chuyện với một cái nút không có tai." Anh nhìn ZERO. "Đã đến lúc trao cho em vũ khí cuối của bộ ba nền tảng: thứ gắn trái tim biết đập cho một trang web — JavaScript."
Vũ khí thứ ba kích hoạt — lần đầu tiên, trang web phản công lại THE BUG.
Hai người trước một cái nút "Đăng ký" bất động
(bấm nút liên tục) Em bấm gãy chuột rồi mà nó vẫn trơ ra. Nút này hỏng thật à?
Không hỏng. Nó điếc. Em đang nói chuyện với một cái nút không có tai.
…Nút thì làm gì có tai?
(gõ một dòng) Thì mình lắp cho nó. Đây: "Này nút, khi nào có người bấm vào, hãy làm việc này." Cái "khi nào có người bấm" đó gọi là sự kiện (event).
(bấm lại, nút bật ra dòng chữ "Đăng ký thành công") Nó… nghe thấy em rồi!
Trang web không tự biết bạn vừa bấm, gõ, hay kéo chuột. Bạn phải "lắp tai" cho từng phần tử bằng cách lắng nghe sự kiện. Đó là cách JavaScript biến trang tĩnh thành thứ biết tương tác.
JavaScript (viết tắt JS) là ngôn ngữ trao cho trang web hành động và phản ứng. Bấm thì menu mở ra, gõ thì kiểm tra dữ liệu, hết giờ thì màn hình đổi — mọi "chuyển động" đều là tác phẩm của JS.
HTML = khung xương (cơ thể) · CSS = vẻ ngoài (quần áo) · JavaScript = hành vi (cơ bắp & thần kinh). Đủ ba thứ, web mới thật sự sống. Bạn vừa nắm bộ ba quyền năng của web.
Là một chiếc hộp có dán nhãn (tên) để chứa một giá trị: một con số, một đoạn chữ… Bạn đặt tên cho hộp, rồi gọi tên đó để lấy lại giá trị bất cứ lúc nào.
Là gói nhiều mệnh lệnh thành một và đặt cho nó một cái tên. Tạo một lần, sau đó chỉ cần gọi tên là cả gói lệnh chạy lại — khỏi viết lại từ đầu.
Giờ nút bấm đã sống. Vừa bấm, hàm liền chạy, một hộp thông báo bật lên. Trang web đã bắt đầu phản ứng với người dùng.
Cho phép chương trình hành động khác nhau tùy tình huống. "Nếu (if) điều này đúng thì làm A, nếu không (else) thì làm B". Đây là cách trao khả năng phán đoán cho máy.
Giả sử bạn muốn in ra "Cố lên!" mười lần. Chẳng lẽ gõ mười dòng? Vòng lặp giúp máy lặp lại một việc bao nhiêu lần tùy ý.
Cấu trúc giúp lặp lại một đoạn lệnh nhiều lần. Phổ biến nhất là vòng for: "làm việc này, lặp lại đúng N lần."
Ba phần trong ngoặc: bắt đầu từ đâu (let i=1), lặp đến khi nào (i<=5), mỗi vòng thay đổi ra sao (i++ là tăng i thêm 1). Đừng học thuộc — hãy đọc: "bắt đầu từ 1, chừng nào còn ≤ 5 thì làm, mỗi lần tăng 1."
Sức mạnh thật sự của JS
Sức mạnh thật sự của JS là thay đổi trang ngay khi người dùng thao tác. Ví dụ kinh điển: bấm nút thì đổi chữ.
document.getElementById("…") là cách JS "tìm" một phần tử trên trang qua id của nó. Tìm được rồi, bạn đổi innerText (chữ bên trong) là nội dung thay đổi ngay trước mắt người dùng.
1. Muốn lặp một việc 10 lần, dùng gì?
Vòng lặp for: for (let i=1; i<=10; i++) { … }
2. Làm sao để JS tìm một phần tử trên trang?document.getElementById("tên-id") — tìm theo id đã đặt trong HTML.
3. "let codeName = 'ZERO'" nghĩa là gì?
Tạo một biến tên codeName, chứa đoạn chữ "ZERO".
▣ Nhiệm vụ 03 — trận quyết chiến
☐ Thêm một <button> vào my.html
☐ Tạo một hàm bên trong thẻ <script>
☐ Nối nút với hàm đó bằng onclick
☐ Bấm nút — nếu hộp thông báo hiện ra, bạn đã hoàn thành tương tác đầu tiên
HTML cho web hình hài · CSS cho web vẻ ngoài · JavaScript cho web một trái tim biết đập. Bạn vừa làm chủ cả ba.
⚿ Không có trên Google · ghi chép từ người đi trước
✕ Không hiểu == khác === — dùng nhầm gây bug ẩn rất khó tìm.
✕ Sửa trực tiếp dữ liệu gốc thay vì tạo bản sao — làm hỏng state của cả ứng dụng.
✕ Quên rằng map/filter trả về mảng mới, vẫn cố sửa mảng cũ.
✕ Đặt tên biến a, data, temp — người review không hiểu bạn định làm gì.
✕ Không xử lý dữ liệu rỗng (null/undefined) — app crash ngay khi gặp ca lạ.
Vì sao quan trọng: JavaScript là nơi logic sống. Một dòng JS cẩu thả không chỉ xấu — nó làm sập tính năng thật mà khách đang dùng.
Nút "Thêm vào giỏ" bấm không ăn trên production. Ai vừa đẩy code lên thế?
Để em xem console… Có lỗi Cannot read property of undefined anh ạ. Em quên check mảng rỗng.
Đúng rồi. Luôn hỏi "nếu dữ liệu trống thì sao?" trước khi đẩy code. Thêm điều kiện rồi test lại nhé.
✦ Trợ thủ AI · dùng đúng cách
💬 "Giải thích đoạn JavaScript này từng dòng, và chỉ ra nó sẽ lỗi trong trường hợp dữ liệu nào."
💬 "Viết lại đoạn vòng lặp này bằng map/filter cho gọn, giải thích vì sao cách đó tốt hơn."
Claude · ChatGPT · Cursor · Copilot — công cụ chỉ mạnh khi bạn đủ hiểu để đặt đúng câu hỏi.
"Hôm nay cái nút của mình… đã nghe thấy mình. Mình bấm, nó trả lời. Nghe nhỏ bé thôi, nhưng mình ngồi lặng đi mất một lúc. Ba đêm trước mình còn không biết một trang web được làm từ gì. Giờ mình vừa làm một thứ biết phản ứng với con người.
Nhưng tối nay tiền bối có gì đó rất lạ. Khi con bug bị chặn, lẽ ra anh phải vui. Vậy mà anh nhìn màn hình như đang nhìn một bóng ma."
Khúc kết chương — bí mật của tiền bối
Khi con bug bị chặn đứng, ZERO quay sang định reo lên, nhưng khựng lại. Tiền bối đang nhìn màn hình với một biểu cảm lạ — không phải vui mừng, mà là một nỗi đau cũ vừa bị khơi lại.
Anh sao vậy?
Ba năm trước, anh cũng từng kèm một người mới. Cậu ấy giỏi — giỏi hơn em bây giờ nhiều. Nhưng anh đã thúc ép quá mức. Một đêm, cậu ấy mắc một lỗi nhỏ trong hệ thống thật, và… anh đã mắng cậu ấy trước mặt cả đội. Hôm sau, cậu ấy nghỉ việc. Không một lời từ biệt. Anh không bao giờ gặp lại nữa.
ZERO chợt hiểu vì sao anh luôn kiên nhẫn đến lạ. Anh đang sửa chữa một lỗi lầm cũ — qua cô.
Tiền bối đưa tay phóng to chữ ký "A." trên màn hình, nhìn nó thật lâu — như nhìn một gương mặt từ quá khứ.
Kẻ trong bóng tối — ra lệnh cho AI tự tấn công. "A." không gõ phím; hắn ra lệnh, và máy tự viết mã.
▤ Hồ sơ nghề nghiệp · sau JavaScript
Đây là cột mốc lớn — đủ ba vũ khí nền tảng để bắt đầu sự nghiệp frontend.
Người rời đi ba năm trước và kẻ tấn công đêm qua… viết code giống hệt nhau.
Người gửi dùng đúng phong cách đặt tên của một nhân viên cũ NOX TECH.
Chương 3.5 // vũ khí thứ ba, nâng cấp
자바스크립트 심화
"Em đã có ba vũ khí. Nhưng JavaScript còn nhiều tầng sâu hơn — và em cần chúng để làm app thật."
Được giao đọc một đoạn code thật của đội, ZERO mở file ra — và khựng lại. Đầy những dấu ngoặc vuông, dấu ngoặc nhọn, dấu chấm nối tiếp nhau: users[0].name, danhSach.map(…). Cô biết từng chữ cái, nhưng ghép lại thì mù tịt. "Sao code thật trông khác xa những gì em học thế này?"
"Vì em mới học bảng chữ cái — biến, hàm, điều kiện. Giờ là lúc ghép chữ thành câu. Ba thứ này: mảng, đối tượng, sự kiện — xuất hiện trong gần như mọi dòng JavaScript thật. Nắm được chúng, em đọc được code của bất kỳ ai. Kể cả code của kẻ đang tấn công ta."
Là một biến chứa nhiều giá trị theo thứ tự, thay vì chỉ một. Như một hộp có nhiều ngăn được đánh số. Dùng để lưu danh sách: tên người dùng, sản phẩm, công việc…
Phần tử đầu tiên là vị trí [0], thứ hai là [1]… Điều này gây bối rối cho mọi người mới, nhưng quen rất nhanh. push thêm phần tử vào cuối, length cho biết mảng có bao nhiêu phần tử.
Là những "việc xảy ra" mà người dùng tạo ra: bấm chuột (click), gõ phím (keypress), di chuột (mouseover)… JavaScript "lắng nghe" các sự kiện này và phản ứng lại — đây là linh hồn của trang web tương tác.
Bảo một phần tử: "khi có sự kiện X thì làm Y". Đây là cách chuyên nghiệp hơn so với onclick viết thẳng trong HTML, và là thứ bạn sẽ gặp trong mọi dự án thật.
1. Phần tử đầu tiên của mảng nằm ở vị trí số mấy?
Vị trí [0] — mảng đếm từ 0.
2. Object dùng để làm gì?
Gom nhiều thông tin liên quan về một thứ vào một chỗ, dạng "tên: giá trị".
3. addEventListener("click", …) làm gì?
Lắng nghe sự kiện bấm chuột trên phần tử, và chạy hàm khi sự kiện xảy ra.
Mục tiêu: app To-do hoạt động được
Một ô nhập việc, một nút thêm, và danh sách việc hiện ra bên dưới. Bấm vào việc để đánh dấu hoàn thành. Đây là app tương tác đầu tiên của bạn — ghép đủ cả mảng, sự kiện và DOM.
Nó dùng: lấy giá trị từ ô nhập (o.value), tạo phần tử mới (createElement), lắng nghe sự kiện (addEventListener), và thêm vào trang (appendChild). Đây chính là cách mọi ứng dụng web tương tác hoạt động — chỉ phức tạp hơn về quy mô.
| Nâng cấp | Gợi ý |
|---|---|
| Nút xóa cho mỗi việc | Thêm một nút nhỏ, dùng li.remove() |
| Đếm số việc còn lại | Dùng một biến, cập nhật mỗi khi thêm/xong |
| Lưu lại khi tải lại trang | Học về localStorage (bước tiếp theo) |
| Tô màu theo độ ưu tiên | Thêm class CSS tùy mức quan trọng |
☐ Gõ lại đầy đủ HTML + JS ở trên thành app chạy được
☐ Thử thêm vài việc, bấm để đánh dấu xong
☐ Chọn ít nhất 1 nâng cấp để làm thêm (gợi ý: nút xóa)
☐ Đẩy lên GitHub bằng những gì sẽ học ở chương Git
ZERO bấm "Thêm", và việc đầu tiên hiện ra. Cô thêm việc thứ hai, thứ ba. Bấm vào một việc — nó gạch ngang. Cô ngả người ra ghế, nhìn thứ mình vừa tạo ra: không phải một bài tập, mà một công cụ thật sự dùng được. "Em làm được một cái app rồi," cô thì thầm. Tiền bối chỉ cười: "Và đó mới chỉ là cái đầu tiên thôi."
Mục này hướng dẫn tự tay gõ code. Nếu bạn theo hướng cầu nối, phiên dịch hay sales IT và chưa cần code thật, có thể đọc lướt để nắm ý rồi đi tiếp — không ảnh hưởng mạch truyện. Khi nào muốn thử, hãy quay lại đây.
Sổ tay // làm app biết nhớ
— App To-do của bạn quên hết khi tải lại trang. Hãy dạy nó cách nhớ. —
ZERO khoe app To-do với tiền bối, mặt rạng rỡ. Anh gật gù, rồi nhấn F5 tải lại trang — và mọi việc cô vừa thêm biến mất sạch. Mặt cô xịu xuống. "Đừng buồn," anh cười. "Đó là vì app chưa biết 'nhớ'. Hôm nay anh dạy em cho nó một bộ não."
Mọi thứ trong JavaScript sống trong bộ nhớ tạm — khi tải lại trang, bộ nhớ đó xóa sạch để bắt đầu mới. Để dữ liệu "sống sót" qua mỗi lần tải, ta cần lưu nó vào một nơi bền hơn. Cách đơn giản nhất cho người mới: localStorage.
Là một "ngăn tủ" nhỏ ngay trong trình duyệt, cho phép lưu dữ liệu dạng chữ tồn tại lâu dài — kể cả khi đóng trình duyệt rồi mở lại. Lý tưởng để lưu những thứ nhỏ: cài đặt, danh sách việc, lựa chọn của người dùng.
ZERO cất từng việc vào "chiếc hộp trí nhớ" của trình duyệt. Nhấn F5, tắt mở lại — danh sách vẫn còn nguyên. App của cô vừa biết nhớ.
setItem (lưu), getItem (lấy), removeItem (xóa). localStorage chỉ lưu được chữ (text), nên khi lưu mảng/object phải đổi sang chữ bằng JSON.stringify(), và đổi ngược lại bằng JSON.parse() khi lấy ra.
localStorage chỉ lưu trên chính máy/trình duyệt đó — không đồng bộ giữa các thiết bị. Để dữ liệu đi theo người dùng khắp nơi, cần lưu trên server/database. localStorage tuyệt cho việc nhỏ, nhưng không thay được database thật.
☐ Thêm localStorage vào app: mỗi khi thêm việc thì lưu lại
☐ Khi tải trang, đọc lại danh sách đã lưu và hiển thị
☐ Thử thêm vài việc, nhấn F5 — chúng vẫn còn đó!
☐ Cảm nhận khoảnh khắc app của bạn "biết nhớ" lần đầu
ZERO thêm vài dòng code, rồi hồi hộp nhấn F5. Trang tải lại… và danh sách việc vẫn còn nguyên. Cô bật cười thành tiếng. Một thứ nhỏ bé thôi, nhưng với cô nó như phép màu: app của cô vừa có được trí nhớ đầu tiên.
Đính kèm: một tệp .zip. Bên trong là app To-do của ZERO — viết lại hoàn hảo, bởi máy.
ZERO ngồi chết lặng. Hắn nói đúng. Cô mở tệp đính kèm — đúng là app của cô, nhưng sạch hơn, gọn hơn, như thể có ai đó đã sống mười năm trong nghề viết hộ. Trong một giây, tất cả những đêm thức trắng gõ từng dòng localStorage.setItem bỗng trở nên vô nghĩa.
▶ 02:00 sáng · ZERO quay màn hình về phía tiền bối
Anh nhìn đi. Nó viết lại app của em trong chín giây. AI giờ code được hết rồi… (giọng khẽ lại) vậy em học mấy thứ này làm gì nữa?
(không nhìn cái app, mà nhìn thẳng vào cô) Cho anh hỏi một câu. Khách hàng nói: "Làm cho tôi cái gì đó giống Instagram, nhưng dành cho người yêu chó, mà phải sang, đừng rối, kiểu trẻ trung nhưng đừng trẻ con." — Em bảo AI viết đi. Nó viết được không?
(ngập ngừng) …Nó sẽ hỏi lại "sang" là sang thế nào.
Không. Nó đoán. Và nó đoán theo trung bình của cả triệu trang web nó từng thấy. AI viết được dòng code. Nhưng nó không biết nên viết dòng nào. Nó không ngồi trong phòng họp khi khách đổi ý lần thứ tư. Nó không hiểu vì sao một cái nút phải nằm ở góc đó chứ không phải góc kia. Yêu cầu của con người luôn mơ hồ — và biến cái mơ hồ thành cái rõ ràng, đó là phần AI không làm được.
"A." có AI viết code nhanh như chớp. Nhưng hắn vẫn cần một thứ: một con người hiểu hệ thống đủ sâu để biết tấn công vào đâu. Đó là lý do hắn từng là người trong đội. Và cũng là lý do em phải học — không phải để gõ nhanh hơn máy, mà để hiểu thứ máy không hiểu.
ZERO nhìn lại cái app "hoàn hảo" của "A." — và lần đầu cô thấy nó thiếu một thứ: nó không biết vì sao nó tồn tại. Code thì máy viết được. Nhưng hiểu con người cần gì — đó vẫn là việc của con người.
Hết chương 03 // 02:00 sáng
Ba vũ khí nền tảng — HTML, CSS, JavaScript — giờ đã nằm trong tay ZERO. Nhưng đêm nay, "A." vừa dạy cô một bài học khác: AI viết được mọi dòng code… trừ dòng quan trọng nhất.
62:12:00 ▸ 58:30:00
Còn 58 giờ. Một sản phẩm thật cần nhiều hơn một người — và mỗi người trong đội đang giấu một điều. Một trong số họ đã dạy AI cách tấn công. Một trong số họ chính là "A."
Bạn không đơn độc
Sáu tin nhắn từ sáu người lạ. Bước vào một đội IT thật — nơi vai trò, niềm tin và nghi ngờ đan vào nhau. 네 번째 무기 — 동료
Bạn vừa đọc xong Chương 03. Sự thật về kẻ tấn công đang chờ ở Chương 04.
🤍 Cùng xuất bản ZERO — đặt trước giá sáng lập
Đọc online MIỄN PHÍ tất cả các chương (bản giản lược). Bản online FULL — đủ mọi chương & mọi phần chuyên sâu, không lược — chỉ 89k. Khi đủ 500 đơn, sách được in màu & xuất bản; chưa đủ → hoàn 100%.
89k / 229k · bản online FULL / bản in (giá sáng lập)
🎁 Bản in tặng kèm bản online FULL · 🏛️ tên "Nhà đồng sáng lập" in cuối sách · 🛡️ chưa đủ 500 thì hoàn 100%.
Cảm ơn bạn đã đọc đến đây 🤍 Hẹn gặp ZERO ở Chương 04.
Không phải tiền mua sách — đây là khoản donate ủng hộ để team viết tiếp phần mới & xuất bản "MẬT DANH: ZERO". 🎁 Nếu sách được xuất bản, người donate được tặng miễn phí 1 cuốn. Đọc online luôn miễn phí nhé!