034.1 Bài 1
Chứng chỉ: |
Web Development Essentials |
---|---|
Phiên bản: |
1.0 |
Chủ đề: |
034 Lập trình JavaScript |
Mục tiêu: |
034.1 Thực thi và Cú pháp của JavaScript |
Bài học: |
1 trên 1 |
Giới thiệu
Các trang web được phát triển bằng ba công nghệ tiêu chuẩn: HTML, CSS và JavaScript. JavaScript là ngôn ngữ lập trình cho phép trình duyệt tự động cập nhật nội dung trang web. JavaScript thường được thực thi bởi cùng một trình duyệt được sử dụng để xem trang web. Điều này có nghĩa là tương tự như CSS và HTML, hành vi của bất kỳ mã nào chúng ta viết cũng có thể sẽ khác nhau giữa các trình duyệt khác nhau. Nhưng hầu hết các trình duyệt phổ biến đều tuân thủ đặc tả ECMAScript. Đây là một tiêu chuẩn thống nhất việc sử dụng JavaScript trong web và sẽ là cơ sở cho bài học này cùng với đặc tả HTML5 dùng để quy định cách JavaScript được đưa vào một trang web để trình duyệt thực thi.
Chạy JavaScript trong Trình duyệt
Để thực thi JavaScript, trình duyệt cần lấy mã trực tiếp như một phần của HTML tạo nên trang web hoặc dưới dạng URL cho biết vị trí để tệp lệnh được thực thi.
Ví dụ sau đây sẽ cho thấy cách để đưa mã trực tiếp vào tệp HTML:
<html>
<head>
</head>
<body>
<h1>Website Headline</h1>
<p>Content</p>
<script>
console.log('test');
</script>
</body>
</html>
Mã đã được bao bọc bên trong các thẻ <script>
và </script>
. Mọi thứ nằm trong các thẻ này sẽ được trình duyệt thực thi trực tiếp khi tải trang.
Vị trí của phần tử <script>
trong trang sẽ cho biết khi nào nó sẽ được thực thi. Một tài liệu HTML sẽ được phân tích cú pháp từ trên xuống dưới và trình duyệt sẽ quyết định khi nào sẽ hiển thị các phần tử trên màn hình. Trong ví dụ ở trên, các thẻ <h1>
và <p>
của trang web đã được phân tích cú pháp và có khả năng được hiển thị trước khi tệp lệnh chạy. Nếu mã JavaScript trong thẻ <script>
cần nhiều thời gian để thực thi thì trang vẫn hiển thị mà không gặp bất kỳ sự cố nào. Tuy nhiên, nếu tệp lệnh đã được đặt phía trên các thẻ khác, khách truy cập trang web sẽ phải đợi cho đến khi tệp lệnh thực thi xong trước khi xem được trang. Vì lý do này, các thẻ <script>
thường được đặt ở một trong hai vị trí:
-
Ở cuối của phần thân HTML, để tệp lệnh là phần cuối cùng được thực thi. Việc đặt như vậy khi mã thêm nội dung nào đó vào trang sẽ không thật sự hữu ích nếu không có nội dung. Một ví dụ có thể là việc thêm chức năng vào một nút, nút này phải tồn tại thì chức năng mới có ý nghĩa.
-
Bên trong phần tử
<head>
của HTML. Điều này đảm bảo rằng tệp lệnh sẽ được thực thi trước khi phần thân HTML được phân tích cú pháp. Nếu muốn thay đổi hành vi tải của trang hoặc có điều gì đó cần được thực thi trong khi trang vẫn chưa được tải đầy đủ, ta có thể đặt tệp lệnh tại đây. Ngoài ra, nếu có nhiều tệp lệnh phụ thuộc vào một tệp lệnh cụ thể, ta có thể đặt tệp lệnh chung đó lên đầu để đảm bảo rằng nó sẽ được thực thi trước các tệp lệnh khác.
Vì nhiều lý do, bao gồm cả khả năng quản lý, ta nên đặt mã JavaScript vào các tệp riêng biệt nằm ngoài mã HTML. Các tệp JavaScript bên ngoài sẽ được bao gồm bằng cách sử dụng thẻ <script>
với thuộc tính src
, như sau:
<html>
<head>
<script src="/button-interaction.js"></script>
</head>
<body>
</body>
</html>
Thẻ src
sẽ cho trình duyệt biết vị trí của nguồn của tệp, nghĩa là tệp chứa mã JavaScript. Vị trí ở đây có thể là một tệp trên cùng một máy chủ (như trong ví dụ trên) hoặc bất kỳ URL nào có thể truy cập trên web (chẳng hạn như https://www.lpi.org/example.js
). Giá trị của thuộc tính src
phải tuân theo quy ước tương tự như khi nhập tệp CSS hoặc tệp hình ảnh, tức là nó có thể là giá trị tương đối hoặc tuyệt đối. Khi gặp một thẻ tệp lệnh có thuộc tính src
, trình duyệt sẽ cố gắng lấy tệp nguồn bằng cách sử dụng yêu cầu HTTP GET
. Do đó, các tệp ngoại vi phải ở trạng thái có thể truy cập được.
Khi sử dụng thuộc tính src
, bất kỳ mã hoặc văn bản nào được đặt giữa các thẻ <script>…</script>
đều sẽ bị bỏ qua theo đặc tả HTML.
<html>
<head>
<script src="/button-interaction.js">
console.log("test"); // <-- This is ignored
</script>
</head>
<body>
</body>
</html>
Có các thuộc tính khác mà ta có thể thêm vào thẻ script
để chỉ định thêm cách trình duyệt nhận và xử lý tệp sau đó như thế nào. Danh sách sau đây sẽ đi vào chi tiết về các thuộc tính quan trọng:
async
-
Có thể được sử dụng trên các thẻ
script
và sẽ hướng dẫn trình duyệt tìm nạp tệp lệnh trong nền để không làm gián đoạn quá trình tải trang. Quá trình tải trang sẽ vẫn bị gián đoạn sau khi trình duyệt nhận được tệp lệnh bởi trình duyệt phải phân tích cú pháp tệp lệnh. Việc này sẽ được thực hiện ngay lập tức sau khi tệp lệnh đã được tìm nạp hoàn toàn. Thuộc tính này là Boolean; do đó, ta chỉ cần viết thẻ như sau mà không cần cung cấp giá trị:<script async src="/script.js"></script>
. defer
-
Tương tự như
async
, thuộc tính này sẽ hướng dẫn trình duyệt không chặn quá trình tải trang trong khi tìm nạp tệp lệnh. Thay vào đó, trình duyệt sẽ trì hoãn việc phân tích cú pháp tệp lệnh. Trình duyệt sẽ đợi cho đến khi toàn bộ tài liệu HTML được phân tích cú pháp và chỉ khi đó nó mới phân tích cú pháp tệp lệnh trước khi thông báo rằng tài liệu đã được tải hoàn toàn. Giống nhưasync
,defer
là một thuộc tính Boolean và cũng được sử dụng theo cách tương tự. Vìdefer
cũng có ý nghĩa tương tự nhưasync
nên ta không nên chỉ định cả hai thẻ cùng với nhau.NoteKhi một trang đã được phân tích cú pháp hoàn toàn, trình duyệt sẽ cho biết rằng nó đã sẵn sàng hiển thị bằng cách kích hoạt sự kiện
DOMContentLoaded
. Khi đó, khách truy cập sẽ có thể xem tài liệu. Do đó, JavaScript được bao gồm bên trong<head>
sẽ luôn có thể hoạt động trên trang trước khi nó được hiển thị (ngay cả khi ta chỉ định cả thuộc tínhdefer
). type
-
Biểu thị loại tệp lệnh mà trình duyệt sẽ mong đợi trong thẻ, mặc định sẽ là JavaScript (
type="application/javascript"
). Vì vậy, thuộc tính này sẽ không cần thiết khi bao gồm mã JavaScript hoặc trỏ đến tài nguyên JavaScript bằng thẻsrc
. Nói chung, tất cả các loại MIME đều có thể được chỉ định, nhưng chỉ các tệp lệnh được ký hiệu là JavaScript mới được trình duyệt thực thi. Có hai trường hợp sử dụng thực tế cho thuộc tính này: yêu cầu trình duyệt không thực thi tệp lệnh bằng cách đặttype
thành một giá trị tùy ý nhưtemplate
hoặcother
, hoặc yêu cầu trình duyệt biết rằng tệp lệnh là một mô-đun ES6. Chúng ta sẽ không đề cập đến các mô-đun ES6 trong bài học này.
Warning
|
Khi nhiều tệp lệnh có thuộc tính |
Bảng Điều khiển Trình duyệt
Mặc dù thường được thực thi như một phần của trang web, ta cũng có một cách khác để thực thi JavaScript: thông qua bảng điều khiển trình duyệt. Tất cả các trình duyệt máy tính để bàn hiện đại đều sẽ cung cấp một menu mà qua đó ta có thể thực thi mã JavaScript trong công cụ JavaScript của trình duyệt. Điều này thường được thực hiện để kiểm tra mã mới hoặc gỡ lỗi các trang web hiện có.
Có nhiều cách để truy cập bảng điều khiển trình duyệt, tùy thuộc vào trình duyệt. Cách dễ nhất là thông qua các phím tắt. Sau đây là các phím tắt cho một số trình duyệt hiện đang được sử dụng:
- Chrome
-
Ctrl+Shift+J (Cmd+Option+J trên Mac)
- Firefox
-
Ctrl+Shift+K (Cmd+Option+K trên Mac)
- Safari
-
Ctrl+Shift+? (Cmd+Option+? trên Mac)
Ta cũng có thể nhấp chuột phải vào một trang web và chọn tùy chọn “Inspect” (Kiểm tra) hoặc “Inspect Element” (Kiểm tra Phần tử) để mở trình kiểm tra - đây là một công cụ khác của trình duyệt. Khi trình kiểm tra mở ra, một bảng điều khiển mới sẽ xuất hiện. Trong bảng điều khiển này, ta có thể chọn tab “Console” để hiển thị bảng điều khiển trình duyệt.
Sau khi kéo bảng điều khiển lên, ta có thể thực thi JavaScript trên trang bằng cách nhập trực tiếp JavaScript vào trường nhập liệu. Kết quả của bất kỳ mã được thực thi nào cũng sẽ được hiển thị trên một dòng riêng biệt.
Câu lệnh JavaScript
Vì chúng ta đã biết cách thực thi một tệp lệnh, hãy cùng tìm hiểu những khái niệm cơ bản để một tệp lệnh thực sự được thực thi. Tệp lệnh JavaScript là một tập hợp các câu lệnh và khối. Câu lệnh ví dụ là console.log('test')
. Phần hướng dẫn này sẽ yêu cầu trình duyệt xuất từ test
ra bảng điều khiển trình duyệt.
Mọi câu lệnh trong JavaScript đều sẽ được kết thúc bằng dấu chấm phẩy (;
). Điều này sẽ cho trình duyệt biết rằng câu lệnh đã được thực hiện và một câu lệnh mới có thể được bắt đầu. Hãy xem đoạn lệnh sau:
var message = "test"; console.log(message);
Chúng ta đã viết hai câu lệnh. Mọi câu lệnh đều được kết thúc bằng dấu chấm phẩy hoặc ở cuối tệp lệnh. Vì để cho dễ đọc, chúng ta có thể đặt các câu lệnh trên các dòng riêng biệt. Bằng cách này, đoạn lệnh cũng có thể được viết là:
var message = "test";
console.log(message);
Điều này có thể thực hiện được vì tất cả các khoảng trắng giữa các câu lệnh như khoảng trắng, dấu xuống dòng hoặc tab đều sẽ bị bỏ qua. Khoảng trắng cũng thường được đặt giữa các từ khóa riêng lẻ trong các câu lệnh, nhưng điều này sẽ được giải thích rõ hơn trong bài học sắp tới. Các câu lệnh cũng có thể được để trống hoặc chỉ bao gồm khoảng trắng.
Nếu một câu lệnh không hợp lệ vì nó chưa được kết thúc bằng dấu chấm phẩy thì ECMAScript sẽ cố gắng tự động chèn các dấu chấm phẩy thích hợp dựa trên một bộ quy tắc phức tạp. Quy tắc quan trọng nhất là nếu một câu lệnh không hợp lệ bao gồm hai câu lệnh hợp lệ được phân tách bằng một dòng mới, hãy chèn dấu chấm phẩy vào dòng mới. Ví dụ: đoạn mã sau không tạo thành một câu lệnh hợp lệ:
console.log("hello")
console.log("world")
Nhưng một trình duyệt hiện đại sẽ tự động thực thi nó như thể nó có các dấu chấm phẩy thích hợp:
console.log("hello");
console.log("world");
Như vậy, ta có thể bỏ qua dấu chấm phẩy trong một số trường hợp nhất định. Tuy nhiên, vì các quy tắc chèn dấu chấm phẩy tự động rất phức tạp, chúng ta nên luôn luôn chấm dứt câu lệnh của mình đúng cách để tránh các lỗi không mong muốn.
Chú thích trong JavaScript
Các đoạn mã lớn sẽ có thể trở nên rất phức tạp. Có thể chúng ta sẽ muốn chú thích về những gì mình đang viết để khiến cho đoạn mã trở nên dễ đọc hơn, cho một ai đó khác hoặc cho chính bản thân mình trong tương lai. Ngoài ra, có thể ta sẽ muốn đưa thông tin meta vào tệp lệnh, chẳng hạn như thông tin bản quyền hoặc thông tin về thời điểm và lý do viết tệp lệnh.
Để có thể chèn các thông tin meta như vậy, JavaScript có hỗ trợ việc chú thích. Một nhà phát triển có thể chèn các ký tự đặc biệt trong tệp lệnh để biểu thị một số phần nhất định của tệp lệnh dưới dạng một chú thích, phần này sẽ bị bỏ qua khi thực thi. Sau đây là một phiên bản được chú thích tương đối cụ thể của tệp lệnh mà chúng ta đã thấy ở trên.
/*
This script was written by the author of this lesson in May, 2020.
It has exactly the same effect as the previous script, but includes comments.
*/
// First, we define a message.
var message = "test";
console.log(message); // Then, we output the message to the console.
Chú thích không phải là câu lệnh và không cần kết thúc bằng dấu chấm phẩy. Thay vào đó, chúng tuân theo các quy tắc chấm dứt của riêng mình, tùy thuộc vào cách viết. Có hai cách để viết chú thích trong JavaScript:
- Chú thích nhiều dòng
-
Sử dụng
/*
và*/
để báo hiệu bắt đầu và kết thúc chú thích nhiều dòng. Mọi thứ sau/*
cho đến khi*/
xuất hiện lần đầu tiên đều sẽ bị bỏ qua. Loại chú thích này thường được sử dụng để mở rộng nhiều dòng, nhưng nó cũng có thể được sử dụng cho các dòng đơn lẻ hoặc thậm chí là trong một dòng như sau:console.log(/* what we want to log: */ "hello world")
Vì mục tiêu của chú thích nói chung là để tăng khả năng đọc của tệp lệnh, ta nên tránh sử dụng kiểu chú thích này trong một dòng.
- Chú thích một dòng
-
Sử dụng
//
(hai dấu gạch chéo lên phía trước) để chú thích một dòng. Mọi thứ sau dấu gạch chéo kép trên cùng một dòng đều sẽ bị bỏ qua. Trong ví dụ được hiển thị ở trên, mẫu này được sử dụng trước tiên để chú thích toàn bộ dòng. Sau câu lệnhconsole.log(message);
, nó sẽ được dùng để viết chú thích trên phần còn lại của dòng.
Nói chung, chú thích một dòng nên được sử dụng cho một dòng và chú thích nhiều dòng nên dùng cho nhiều dòng ngay cả khi ta có thể sử dụng chúng theo những cách khác. Chúng ta nên tránh việc chú thích trong một câu lệnh.
Chú thích cũng có thể được sử dụng để tạm thời xóa các dòng mã như sau:
// We temporarily want to use a different message
// var message = "test";
var message = "something else";
Bài tập Hướng dẫn
-
Hãy tạo một biến có tên
ColorName
và gán giá trịRED
cho nó. -
Têp lệnh nào sau đây là hợp lệ?
console.log("hello") console.log("world");
console.log("hello"); console.log("world");
// console.log("hello") console.log("world");
console.log("hello"); console.log("world") //;
console.log("hello"); /* console.log("world") */
Bài tập Mở rộng
-
Có bao nhiêu câu lệnh JavaScript có thể được viết trên một dòng mà không sử dụng dấu chấm phẩy?
-
Hãy tạo hai biến có tên
x
vày
, sau đó in tổng của chúng ra bảng điều khiển.
Tóm tắt
Trong bài học này, chúng ta đã học về các cách để thực thi JavaScript và sửa đổi hành vi tải tệp lệnh. Chúng ta cũng đã học về các khái niệm cơ bản của thành phần tệp lệnh và chú thích, đồng thời cũng đã học cách sử dụng lệnh console.log()
.
HTML được sử dụng trong bài học này:
- <script>
-
Thẻ
script
có thể được sử dụng để chèn JavaScript trực tiếp hoặc bằng cách chỉ định một tệp có thuộc tínhsrc
. Nó có thể sửa đổi cách tệp lệnh được tải bằng các thuộc tínhasync
vàdefer
.
Các khái niệm JavaScript được giới thiệu trong bài học này:
;
-
Dấu chấm phẩy được dùng để ngăn cách các câu lệnh. Dấu chấm phẩy đôi khi có thể — nhưng không nên — được bỏ qua.
//
,/*…*/
-
Chú thích có thể được sử dụng để thêm chú giải hoặc thông tin meta vào tệp lệnh hoặc để chặn việc thực thi các câu lệnh.
console.log("text")
-
Ta có thể sử dụng lệnh
console.log()
để xuất văn bản ra bảng điều khiển của trình duyệt.
Đáp án Bài tập Hướng dẫn
-
Hãy tạo một biến có tên
ColorName
và gán giá trịRED
cho nó.var ColorName = "RED";
-
Têp lệnh nào sau đây là hợp lệ?
console.log("hello") console.log("world");
Không hợp lệ: Lệnh
console.log()
đầu tiên không được kết thúc đúng cách và toàn bộ dòng đã không tạo thành một câu lệnh hợp lệ.console.log("hello"); console.log("world");
Hợp lệ: Mỗi câu lệnh đều đã được chấm dứt một cách hợp lệ.
// console.log("hello") console.log("world");
Hợp lệ: Toàn bộ mã sẽ bị bỏ qua vì nó là một chú thích.
console.log("hello"); console.log("world") //;
Không hợp lệ: Câu lệnh cuối cùng bị thiếu dấu chấm phẩy. Dấu chấm phẩy ở cuối sẽ bị bỏ qua vì nó là chú thích.
console.log("hello"); /* console.log("world") */
Hợp lệ: Một câu lệnh hợp lệ được theo sau bởi mã chú thích; mã này sẽ bị bỏ qua.
Đáp án Bài tập Mở rộng
-
Có bao nhiêu câu lệnh JavaScript có thể được viết trên một dòng mà không sử dụng dấu chấm phẩy?
Nếu chúng ta đang ở phần cuối của tệp lệnh, chúng ta có thể viết một câu lệnh và nó sẽ bị loại bỏ bởi phần kết thúc của tệp. Trái lại, bạn sẽ không thể viết một câu lệnh mà không có dấu chấm phẩy với cú pháp mà bạn đã học.
-
Hãy tạo hai biến có tên
x
vày
, sau đó in tổng của chúng ra bảng điều khiển.var x = 5; var y = 10; console.log(x+y);