39 điểm bởi GN⁺ 2025-05-29 | 10 bình luận | Chia sẻ qua WhatsApp
  • Nhân dịp kỷ niệm 30 năm JavaScript trong năm nay, Deno đã tóm lược ngắn gọn lịch sử phát triển của ngôn ngữ này
  • JavaScript khởi đầu là một ngôn ngữ script được phát triển chỉ trong 10 ngày, và nay đã trở thành ngôn ngữ phổ biến nhất thế giới
  • Bài viết giới thiệu một số cột mốc lịch sử quan trọng, cho thấy JavaScript đã phát triển như thế nào và sẽ đi về đâu trong tương lai

A brief history of JavaScript (1994-2025)

[1994]

  • Phát hành Netscape Navigator 1.0

    • Tháng 12/1994, Netscape Navigator 1.0 được phát hành
    • Tốc độ nhanh hơn các trình duyệt trước đó và có GUI là những yếu tố giúp nó được ưa chuộng
    • Cùng với việc hỗ trợ HTML 2.0, nền tảng để JavaScript chạy trên trình duyệt này cũng được hình thành sau đó

[1995]

  • Sự ra đời của JavaScript

    • Tháng 5/1995, Brendan Eich đã phát triển bản thảo đầu tiên của JavaScript chỉ trong 10 ngày
    • Nó được phát triển theo yêu cầu về một ngôn ngữ script có cú pháp tương tự Java, vốn rất phổ biến vào thời điểm đó
    • Tên gọi được quyết định là JavaScript vì mục đích marketing
  • Thông báo chính thức từ Netscape và Sun

    • Tháng 12/1995, JavaScript được công bố là “ngôn ngữ kịch bản hướng đối tượng nhẹ cho web”
    • Khi được công bố với sự ủng hộ của 28 công ty công nghệ, nó cũng được định vị là một ngôn ngữ có tính đến cả môi trường doanh nghiệp

[1996]

  • Phản ứng của Microsoft

    • Tháng 3/1996, Microsoft tích hợp JScript vào Internet Explorer 3
    • JScript có thể liên kết với ActiveX để điều khiển các ứng dụng như Excel
  • Phát hành Navigator 2.0 tích hợp JavaScript 1.0

    • Cũng trong tháng 3 năm đó, JavaScript 1.0 chính thức ra mắt trên Netscape Navigator 2.0
    • Khái niệm DOM (Document Object Model) cũng bắt đầu từ thời điểm này

[1997]

  • Đề xuất tiêu chuẩn hóa lên ECMA

    • Tháng 6/1997, Netscape đề xuất chuẩn hóa JavaScript lên ECMA International
    • Mục đích là để giải quyết vấn đề tương thích với JScript của Microsoft
    • Đặc tả mang tên ECMA-262 được tạo ra, và tên gọi được xác định là ECMAScript
    • Ủy ban TC39 được thành lập để bắt đầu quản lý sự phát triển của ngôn ngữ

[1998]

  • Khởi động dự án Mozilla

    • Tháng 1/1998, để đối phó với thế độc quyền thị trường trình duyệt của Microsoft, Netscape đã mở mã nguồn
    • Tên dự án là “Mozilla”, và sau này dẫn tới nhiều thành quả nguồn mở đa dạng như Firefox, Rust
  • Công bố ECMAScript 2

    • Tháng 9/1998, ECMAScript 2 được công bố chính thức
    • Không có tính năng mới, nhưng mục tiêu chính là đảm bảo tính nhất quán của đặc tả và tài liệu hóa được tinh chỉnh tốt hơn

[1999]

  • IE5 và sự xuất hiện của XMLHttpRequest

    • Tháng 3/1999, IE5 giới thiệu XMLHttpRequest
    • Đây là nền tảng cho công nghệ AJAX về sau
  • JSDoc xuất hiện

    • Tháng 4/1999, JSDoc cho tài liệu hóa JavaScript được giới thiệu
    • Nó chịu ảnh hưởng từ Javadoc của Java và hiện vẫn được dùng như một công cụ tạo tài liệu
  • Công bố ECMAScript 3

    • Tháng 12/1999, ECMAScript 3 được công bố chính thức
    • Với việc bổ sung do-while, biểu thức chính quy, các phương thức chuỗi và xử lý ngoại lệ, nó đã đặt nền móng cho giai đoạn tăng trưởng thực sự của ngôn ngữ
    • Sau đó, nó được dùng như chuẩn thực tế của JavaScript web trong hơn 10 năm

[2001]

  • JSON lần đầu xuất hiện

    • Thông điệp JSON đầu tiên được truyền đi
    • Cấu trúc đối tượng dạng { to, do, text } được dùng trong script bên trong trang web
    • Là một định dạng thông điệp nhẹ dựa trên JavaScript, sau này nó trở thành tiêu chuẩn cho giao tiếp web API
Quảng cáo

[2002]

  • JSLint được giới thiệu

    • Douglas Crockford công bố công cụ kiểm tra cú pháp tĩnh JSLint
    • Nó giúp nâng cao chất lượng mã JavaScript và sau đó dẫn tới cuốn sách “JavaScript: The Good Parts” của ông
  • Phoenix 0.1, tiền thân của Firefox, được phát hành

    • Cộng đồng Mozilla phản đối sự nặng nề của bộ sản phẩm cũ nên đã phát triển trình duyệt nhẹ Phoenix
    • Nó cung cấp các tính năng đột phá như tab browsing và chặn popup → sau này phát triển thành Firefox

[2003]

  • Apple công bố Safari và WebKit

    • Việc giới thiệu trình duyệt Safari và engine WebKit giúp Mac thoát khỏi sự phụ thuộc vào Microsoft
    • Sau này nó trở thành nền tảng cho Mobile Safari trên iPhone

[2004]

  • Gmail và AJAX

    • Giao diện dựa trên AJAX của Gmail đã đặt ra chuẩn UX mới cho web app
    • Trao đổi dữ liệu với server mà không cần reload toàn bộ trang → mở ra kỷ nguyên Web 2.0

[2005]

  • Khái niệm AJAX được xác lập

    • Jesse James Garrett đã chính thức hóa khái niệm “AJAX”
    • Thông qua sự kết hợp JavaScript + XML, một cấu trúc giao tiếp bất đồng bộ với server được định hình
  • Mozilla DevMo ra mắt → phát triển thành MDN

    • MDN, trung tâm tài liệu JavaScript dựa trên tiêu chuẩn, bắt đầu hình thành
    • Nó cung cấp một chuẩn tham chiếu thống nhất cho tài liệu hỗ trợ trình duyệt vốn bị phân mảnh

[2006]

  • jQuery xuất hiện

    • John Resig khởi động dự án jQuery
    • Nó đóng góp lớn vào việc giải quyết các vấn đề cross-browser trong thao tác DOM, xử lý sự kiện, AJAX...
    • API ngắn gọn giúp nó lan rộng bùng nổ

[2007]

  • iPhone ra mắt và không hỗ trợ Flash

    • Apple công bố iPhone, Safari không hỗ trợ Flash
    • Điều này thúc đẩy nhanh hơn quá trình chuyển sang nội dung dựa trên HTML + JavaScript trong môi trường di động

[2008]

  • Netscape Navigator chính thức chấm dứt

    • AOL ngừng phát triển Netscape, cuộc chiến trình duyệt lần thứ nhất kết thúc
    • Sự độc quyền của IE từ Microsoft sau đó dẫn tới các vụ kiện chống độc quyền
  • Xuất bản JavaScript: The Good Parts

    • Cuốn sách của Crockford trở thành cơ hội để đánh giá lại JavaScript như một ngôn ngữ phát triển chuyên nghiệp
  • Google Chrome và engine V8 được công bố

    • Cùng với việc phát hành Chrome, engine JavaScript V8 cũng được công khai
    • Biên dịch JITtối ưu garbage collection giúp cải thiện hiệu năng mạnh mẽ
    • Sau đó nó tạo nền tảng cho sự mở rộng sang phía server như Node.js

[2009]

  • CommonJS xuất hiện

    • Một nỗ lực chuẩn hóa việc dùng mã JS mô-đun hóa trong các môi trường ngoài trình duyệt như server
    • Đây trở thành nền tảng cho cấu trúc mô-đun của hệ sinh thái Node.js sau này
  • Dự án Node.js bắt đầu

    • Ryan Dahl bắt tay phát triển Node.js
    • Nó cho phép JavaScript chạy trong môi trường server, mở rộng thành một ngôn ngữ full-stack
    Quảng cáo
  • Oracle mua lại Sun Microsystems

    • Cùng với Java, quyền thương hiệu JavaScript cũng được chuyển sang Oracle
    • Từ đó phát sinh các vấn đề thương hiệu liên quan đến tên gọi JavaScript
  • Express.js xuất hiện

    • Express.js có commit đầu tiên, là một web framework dựa trên Node.js
    • Nó đề xuất cấu trúc middleware tập trung vào xây dựng REST API
  • Công bố ECMAScript 5

    • Các tính năng như strict mode, hỗ trợ JSON, bổ sung phương thức cho Array... đã hoàn thiện nền tảng cho JS hiện đại
  • CoffeeScript xuất hiện

    • Đây là thử nghiệm cải tiến cú pháp trước thời ES6 với cú pháp ngắn gọn, arrow function, destructuring...
    • Sau này nó gián tiếp ảnh hưởng đến sự phát triển cú pháp JavaScript

[2010]

  • npm 1.0 được phát hành

    • Trình quản lý gói cho JavaScript là npm chính thức ra mắt, bắt đầu chuẩn hóa việc chia sẻ và tái sử dụng mã nguồn
    • Hiện nay nó đã phát triển thành registry nguồn mở lớn nhất thế giới với hơn 3 triệu package
  • WebStorm 1.0 được phát hành

    • JetBrains ra mắt IDE chuyên dụng đầu tiên cho JavaScript
    • Tích hợp các tính năng phân tích tĩnh, phát hiện lỗi, tự động hoàn thành, gỡ lỗi
  • Sự xuất hiện của AngularJS & Backbone.js

    • Khởi đầu cho làn sóng bùng nổ framework SPA
    • Angular tập trung vào khai báo/tiêm phụ thuộc, còn Backbone tập trung vào mệnh lệnh/tính tối giản
    • Từ giai đoạn này bắt đầu xuất hiện hiện tượng framework liên tục ra đời rồi biến mất ("Framework churn")

[2011]

  • Node.js được port lên Windows

    • Nhờ sự hợp tác giữa Joyent và Microsoft, Node.js có thể chạy trên Windows
    • Phát triển thư viện libuv → cung cấp nền tảng tích hợp I/O bất đồng bộ
    • Sau đó trở thành khởi đầu cho bước tiến mã nguồn mở của Microsoft, dẫn tới TypeScript, VSCode, chiến lược Azure...

[2012]

  • Sự xuất hiện của Webpack

    • Với vai trò là công cụ đóng gói tài nguyên web, mở rộng hệ thống module sang phía client
    • Sau này được chọn làm hệ thống build cốt lõi cho React, Angular, Vue...
  • TypeScript 0.8 ra mắt

    • Microsoft công bố siêu tập JavaScript dựa trên kiểu tĩnh
    • Cung cấp cấu trúc phù hợp cho các dự án quy mô lớn, về sau ảnh hưởng đến tiêu chuẩn ES

[2013]

  • Atom Shell, tiền thân của Electron, bắt đầu

    • Cho phép phát triển ứng dụng desktop bằng HTML/CSS/JS
    • Được áp dụng trong Slack, Visual Studio Code..., làm thay đổi cách phát triển desktop
  • asm.js được công bố

    • Chuyển đổi mã C/C++ sang JS để có thể thực hiện tính toán hiệu năng cao trong trình duyệt
    • Sau này phát triển thành WebAssembly
  • Định nghĩa stack MEAN

    • Đặt tên cho tổ hợp MongoDB + Express + Angular + Node.js
    • Phổ biến hóa phương thức phát triển full-stack dựa trên JavaScript
  • React ra mắt

    • Facebook sau khi dùng nội bộ đã công bố mã nguồn mở
    • Định hình mô hình phát triển UI dựa trên component
  • Bắt đầu phát triển ESLint

    • Công cụ linting có thể mở rộng do Nicholas C. Zakas khởi xướng
    • Có khả năng tùy biến cao hơn các linter trước đó nên nhanh chóng lan rộng
  • Gulp ra mắt

    • Khác với Grunt thiên về cấu hình, đây là công cụ build streaming dựa trên mã nguồn
    • Hình thành xu hướng tự động hóa tác vụ build bằng JavaScript
Quảng cáo

[2014]

  • Vue.js ra mắt

    • Framework UI lũy tiến do Evan You công bố
    • Dung hòa giữa UI khai báo của React và khả năng template của Angular
  • Express.js được mua lại

    • StrongLoop mua lại Express.js → sau đó tiếp tục được IBM mua lại
    • Do dấy lên vấn đề về tính độc lập của cộng đồng, các framework kế nhiệm như Koa xuất hiện
  • Babel.js bắt đầu (trước đây là 6to5)

    • Giúp cú pháp JS mới nhất vẫn có thể chạy trên trình duyệt cũ
    • Trở thành transpiler tiêu chuẩn của mọi framework
  • Meteor 1.0 ra mắt

    • Được chú ý như công cụ phát triển webapp thời gian thực, đơn stack
    • Sau này ảnh hưởng đến các công nghệ thời gian thực như GraphQL, Firebase...
  • Facebook công bố Flow

    • Công cụ kiểm tra kiểu tĩnh để phát hiện trước lỗi JS
    • Về sau tỷ lệ sử dụng giảm do TypeScript tăng trưởng
  • AWS Lambda được công bố

    • Đưa điện toán serverless dựa trên JavaScript(Node.js) vào sử dụng
    • Thông qua thực thi hàm theo sự kiện, có thể triển khai backend mà không cần quản lý hạ tầng
  • Fork io.js

    • Cộng đồng tách nhánh io.js để phản đối tốc độ phát hành Node.js chậm của Joyent
    • Sau đó được sáp nhập trở lại vào Node.js vào năm 2015

[2015]

  • Thuật ngữ Jamstack xuất hiện

    • Nhấn mạnh tổ hợp JavaScript + API + Markup
    • Khi SSR và SSG được chú ý, trình tạo trang tĩnh cũng nổi lên
  • Thành lập Node.js Foundation

    • Củng cố lại quản trị cộng đồng, bao gồm cả việc hợp nhất với io.js
    • Có sự tham gia của các công ty lớn như IBM, Microsoft...
  • GraphQL ra mắt

    • Ngôn ngữ truy vấn API do Facebook phát triển
    • Đặc trưng bởi cách tiếp cận khai báo, thiết kế kiểu mạnh và tối thiểu hóa yêu cầu tới server
  • Redux ra mắt

    • Bộ chứa trạng thái có thể dự đoán dành cho quản lý state của React
    • Sau này cũng được áp dụng trong Vue, Angular...
  • WebAssembly được công bố

    • Cho phép chạy mã hiệu năng cao như C/C++ trong trình duyệt
    • Là hậu duệ của asm.js, dần trở thành môi trường thực thi phổ dụng cho web
  • Atom 1.0 ra mắt

    • Trình soạn thảo văn bản có thể hack được, dựa trên Electron do GitHub tạo ra
    • Có ảnh hưởng trực tiếp tới VSCode
  • ECMAScript 6 (ES2015) chính thức được công bố

    • Cải tiến cú pháp quy mô lớn như import/export, let/const, Promise, fetch
    • Là phiên bản đặt nền tảng cho JavaScript hiện đại
  • Node.js và io.js hợp nhất

    • Với việc công bố Node.js v4.0, hai dự án được tái hợp nhất thành một
    • Thiết lập chính sách hỗ trợ dài hạn (LTS) và versioning rõ ràng

[2016]

  • Microsoft mã nguồn mở engine Chakra

    • Chakra, engine JS của trình duyệt Edge, được mở mã nguồn
    • Thu hút sự quan tâm của cộng đồng phát triển, nhưng về sau bị lấn át bởi ưu thế của V8 và bị ngừng lại
  • Sự cố Leftpad xảy ra

    • Việc xóa module left-pad đã gây ra sự cố sụp đổ phụ thuộc gói trên diện rộng
    • Trở thành động lực thay đổi chính sách npm
  • VSCode 1.0 ra mắt

    • IDE nhẹ dựa trên Electron và TypeScript
    • Nhanh, mở rộng tốt và hỗ trợ JS/TS xuất sắc nên nhanh chóng phổ biến
    Quảng cáo
  • ECMAScript 2016 được công bố

    • Cập nhật nhỏ như toán tử **array.includes()
  • Angular2 được công bố

    • Kiến trúc component dựa trên TypeScript hoàn toàn khác với AngularJS
    • Nhờ biên dịch AOT và tăng cường bảo mật, nổi lên như một lựa chọn cho doanh nghiệp
  • Next.js 1.0 ra mắt

    • Framework render phía server dựa trên React
    • Thúc đẩy chuẩn hóa phát triển React full-stack có tính đến SEO và hiệu năng

[2017]

  • Commit đầu tiên cho đề xuất Temporal

    • Đề xuất API Temporal nhằm giải quyết các vấn đề của đối tượng Date
    • Được phê duyệt để đưa vào tiêu chuẩn ECMAScript năm 2021, hiện mới chỉ được hỗ trợ trong một số môi trường
  • Prettier 1.0 ra mắt

    • Formatter tự động áp dụng phong cách mã nguồn nhất quán
    • Cũng ảnh hưởng đến sự xuất hiện của Black trong Python và formatter của Rust
  • ECMAScript 2017 được công bố

    • Đưa vào các tính năng JS hiện đại như async/await, Object.entries(), Object.values()
    • Việc sử dụng fetch() trở nên phổ biến
  • Yarn ra mắt

    • Trình quản lý gói nhằm giải quyết sự chậm chạp và xung đột của npm
    • Giới thiệu các tính năng đột phá như yarn.lock, cài đặt song song, cache...
  • Cloudflare Workers ra mắt

    • Mở đầu kỷ nguyên edge computing
    • Mã serverless có thể được thực thi phân tán trên toàn thế giới

[2018]

  • Puppeteer 1.0 ra mắt

    • Công cụ tự động hóa trình duyệt dựa trên Chrome headless
    • Cung cấp API thân thiện với Node.js, gọn gàng hơn so với Selenium
  • TensorFlow.js ra mắt

    • Có thể chạy machine learning trong trình duyệt
    • Xây dựng ứng dụng AI thời gian thực dựa trên WebGL/WebGPU
  • Smooshgate

    • Do xung đột tên Array.flatten, nên được đổi thành flat()
    • Bắt nguồn từ vấn đề tương thích với MooTools
  • Ryan Dahl công bố Deno

    • Cùng với việc nhìn lại các vấn đề của Node, runtime Deno được công bố lần đầu
  • ECMAScript 2018 được công bố

    • Giới thiệu promise.finally(), async iteration, object rest/spread

[2019]

  • OpenJS Foundation ra đời

    • Hợp nhất Node.js Foundation và JavaScript Foundation
    • Hợp nhất quản trị cho các dự án phía server/client
  • Node.js v12: bắt đầu hỗ trợ ESM ở mức thử nghiệm

    • Đưa ES module thử nghiệm thông qua .mjs, type: module...
  • Công bố ECMAScript 2019

    • Bổ sung Object.fromEntries(), String.prototype.trimStart() và nhiều tính năng khác
  • Node.js v13.2: ESM chính thức ổn định

Quảng cáo

[2020]

  • SpaceX Dragon, tiến ra vũ trụ với JS

    • Sử dụng JavaScript cho giao diện màn hình cảm ứng dựa trên Chrome
  • Ra mắt Deno 1.0

    • Cách tiếp cận đổi mới như hỗ trợ TypeScript mặc định, mô hình phân quyền, HTTP import
  • Adobe Flash chính thức kết thúc

    • Môi trường multimedia web lấy JS làm trung tâm được định hình

[2022]

  • Deno gia nhập TC39

    • Tuyên bố tham gia chuẩn hóa JavaScript
  • Kết thúc hỗ trợ IE11

    • Hoàn tất quá trình chuyển dịch sang hệ sinh thái web dựa trên tiêu chuẩn
  • Công bố ECMAScript 2022

    • Bổ sung top-level await, khối tĩnh của lớp và nhiều tính năng khác

[2023]

  • Ra mắt Bun 1.0

    • Runtime thay thế Node.js siêu nhanh được triển khai bằng Zig
    • Tương thích npm, tích hợp công cụ build

[2024]

  • Node.js chọn linh vật Rocket Turtle

    • Nhân vật cuối cùng được chốt thông qua cuộc thi của cộng đồng
  • Công bố ECMAScript 2024

    • Tăng cường xử lý Unicode như toWellFormed()
  • Ra mắt registry JSR

    • Registry chuyên cho module ECMAScript hiện đại của nhóm Deno
    • Tương thích với TypeScript, Deno, Bun, Cloudflare Workers
  • Khởi động phong trào FreeJavaScript

    • Chiến dịch kêu gọi Oracle trả lại thương hiệu JavaScript
    • Có chữ ký của các nhân vật chủ chốt như Brendan Eich
  • Ra mắt Deno 2

    • Cải thiện khả năng tương thích với Node, đồng thời còn chạy quảng cáo, cho thấy cuộc chiến runtime chính thức nóng lên

[2025]

  • Công bố bản port TypeScript sang Go

    • Dự án tsgo đang được triển khai với mục tiêu hiệu năng nhanh hơn hơn 10 lần
    • Dự kiến được chính thức áp dụng từ TypeScript 7.0
  • Tuyên bố mã nguồn mở Copilot Chat

    • Microsoft công bố chiến lược chuyển VSCode thành IDE phát triển AI mã nguồn mở

[Kết luận]

  • JavaScript khởi đầu là một ngôn ngữ script đơn giản, rồi phát triển thành ngôn ngữ phát triển đa dụng bao trùm frontend web, backend, machine learning, hàng không vũ trụ, IDE phát triển AI
  • Cộng đồng mã nguồn mở, sự phát triển liên tục của cú pháp và đổi mới về runtime đã dẫn dắt sự tăng trưởng đó, và trong tương lai nó sẽ tiếp tục vượt ra ngoài web để mở rộng sang những lĩnh vực rộng lớn hơn cùng với các công cụ nhanh hơn và thông minh hơn

10 bình luận

 
princox 2025-12-17

Giờ thì nó không còn là tiêu chuẩn của ngôn ngữ nữa mà đã thành tiêu chuẩn của phần hiện thực... Dù thích hay không, có lẽ nó đã trở thành thứ cú pháp mà ta phải mang theo cả phần legacy.

 
dkang 2025-05-31

Cảm ơn vì tài liệu hữu ích.

 
dontdieych 2025-05-31

IE 3 gần như là đồ bỏ đi. Khi đó Navigator 3 gần như là tiêu chuẩn, nhưng khi IE 4 xuất hiện thì tình thế đã đảo ngược. Hơn nữa, IE 4 còn được cài sẵn mặc định trong Windows.

Navigator 4 cũng có ra mắt, nhưng nó không đủ tốt để xoay chuyển tình hình. Vì thế thị phần của IE tiếp tục tăng lên.

Khi Navigator chuyển sang mã nguồn mở, dự án Mozilla ra đời và bản beta Phoenix xuất hiện; lúc đó người dùng bắt đầu cảm nhận rõ ràng rằng đã có điều gì đó thực sự thay đổi. Tôi cũng vậy. Vì vấn đề nhãn hiệu, tên được đổi thành Firefox, và từ thời điểm này Firefox bắt đầu trở thành đối thủ thực sự xứng tầm của IE.

Có lẽ tên đã đổi theo thứ tự Phoenix -> Firebird -> Firefox. Chắc là vì đã có sẵn một cơ sở dữ liệu tên là Firebird.

 
aer0700 2025-05-30

Đang đọc liền một mạch thì từ đoạn giữa tự nhiên thấy nghẹn lòng.
Mới đây thôi mà cũng lại thấy như chuyện từ rất xa rồi...

 
tsboard 2025-05-29

Bài gốc được tổng hợp cực kỳ tốt. Cả ảnh chụp màn hình lẫn những đoạn mã đầy hoài niệm nữa...! Mong là Deno cũng sẽ phát triển tốt hơn nữa. haha

 
tested 2025-05-29

Có vẻ như sự phát triển của JavaScript được chia thành trước và sau khi Node.js ra mắt.

 
bobross0 2025-05-29

Đồng cảm.

 
dlehals2 2025-05-29

Cùng với Java, quyền thương hiệu JavaScript cũng được chuyển sang Oracle. Đây là lần đầu tôi biết điều này.

 
spp00 2025-05-30

Ngay từ đầu, Sun đã nắm quyền sở hữu nhãn hiệu của JS, và khi Sun bị thâu tóm thì quyền nhãn hiệu JS (cùng với MySQL, v.v.) cũng được chuyển sang Oracle.

 
xguru 2025-05-29

Bài gốc có nhiều hình ảnh và các đoạn mã khác nhau, nên sẽ tốt hơn nếu xem cùng với chúng.