1.1
JavaScript
cho React
Trước khi tìm hiểu
về React, bạn sẽ tìm hiểu một số kiến thức nền tảng JavaScript giúp việc tìm hiểu
về React được thuận tiện hơn.
Từ khi ra đời năm
1995 đến nay, JavaScript đã có rất nhiều thay đổi. Ban đầu, người ta sử dụng
JavaScript để tăng thêm khả năng tương tác cho các phần tử của trang web, như
các nút bấm, thao tác huơ chuột (hover), kiểm tra dữ liệu của form. Sau đó,
JavaScript được quan tâm nhiều hơn với DHTML và Ajax. Ngày nay, với Node.js,
JavaScript đã trở thành một ngôn ngữ lập trình ứng dụng thực sự, có thể sử dụng
để tạo ra một ứng dụng hoàn chỉnh. Hiện nay JavaScript đang được nhiều người
quan tâm.
Sự tiến hóa của
JavaScript được thúc đẩy bởi cộng đồng, các công ty và các nhà phát triển trình
duyệt web. ECMA (European Computer Manufacturers Association – Hiệp hội các nhà
sản xuất máy tính châu Âu) là tổ chức chịu trách nhiệm quản lý những thay đổi của
JavaScript trong các năm qua. Các thay đổi được khởi phát và đệ trình từ các cá
nhân/tổ chức trong cộng đồng, mọi người đều có thể đệ trình các thay đổi tới
ECMA, tổ chức này sẽ quản lý và xét duyệt để đưa các đệ trình vào các đặc tả của
JavaScript.
Như vậy, bạn có
thể sử dụng hai từ tương đương là JavaScript hoặc ECMAScript (viết tắt là ES)
khi nói về ngôn ngữ lập trình JavaScript. Các đặc tả JavaScript của ECMA gồm
nhiều phiên bản, ví dụ: ES2015 (hay ES6), ES2016 (ES7), ES2021 (ES12). Có thể
hiểu, JavaScript là một ngôn ngữ lập trình, còn ECMA là các chuẩn hóa (hay
các phiên bản) của ngôn ngữ JavaScript.
Khi đọc các tài
liệu tiếng Anh bạn sẽ thấy thuật ngữ “Vanilla JavaScript” ám chỉ là JavaScript
thuần (bao gồm cả các bản ES), để phân biệt với các thư viện, framework dựa
trên JavaScript. Việc nắm được các kiến thức, các kĩ thuật lập trình của
JavaScript thuần là một lợi thế rất lớn, giúp bạn dễ dàng học, làm việc với các
thư viện, framework và các chương trình JavaScript khác nhau.
1.1.1 Khai báo biến và phạm vi
Trước ES2015 (hay ES6) để khai báo biến, chỉ có một cách là
sử dụng từ khóa var. Tuy nhiên, các
phiên bản JavaScript từ ES2015 trở về sau, ngoài việc dùng từ khóa var, nó còn cho phép khai báo biến bằng
một số cách khác.
Dùng từ khóa const
const là viết tắt
của constant, nghĩa là hằng. Do là hằng nên bạn không thể thay đổi giá trị của
nó sau khi đã khai báo và gán giá trị lần đầu.
Trong thực tế, có
rất nhiều biến trong JavaScript không nên cho phép thay đổi giá trị, trong trường
hợp này, bạn nên sử dụng từ khóa const để khai báo biến.
Ví dụ, với từ
khóa var, bạn có thể ghi đè giá trị của biến:
var pizza = true;
pizza = false;
console.log(pizza); // false
Các bạn nên viết lại từng
đoạn mã ví dụ và chạy trong trình duyệt, hoặc trong hệ thống Nodejs để xem kết
quả.
Ví dụ chạy trên trình duyệt web:
Cách 1:
– Mở trình duyệt, mở cửa
sổ Developer tools, chọn tab Console
– Nhập đoạn mã nguồn
vào cửa sổ Console, để xuống dòng bấm phím Shift + Enter; bấm phím Enter để chạy
chương trình; dùng hàm clear() hoặc console.clear() để xóa sạch màn hình.
Cách 2:
– Tạo một tập tin với
phần mở rộng là .html (ví dụ test.html)
– Nhập mã nguồn
JavaScript trong cặp thẻ <script></script>
– Mở tập tin test.html
bằng trình duyệt web
– Mở cửa sổ Developer
tools, chọn tab Console để xem kết quả
Ví dụ chạy trong hệ thống Nodejs:
– Cài đặt phần mềm
Nodejs
– Tạo một tập tin mã
nguồn, với phần mở rộng là .js (ví dụ test.js)
– Nhập mã JavaScript
vào tập tin mã nguồn, lưu lại
– Mở cửa sổ dòng lệnh
(cmd hoặc powershell)
– Di chuyển dấu nhắc lệnh
tới vị trí của tập tin mã nguồn
– Gõ lệnh node taptinmanguon.js (ví dụ node
test.js) để thực thi và xem kết quả
Ví dụ, dùng từ khóa const để khai báo và khởi tạo giá trị
cho biến, sau đó bạn không thể thay đổi giá trị của biến:
const pizza = true;
pizza = false; // sẽ có thông báo lỗi
Nhắc lại một chút về khái niệm phạm vi (scope) trong ngôn ngữ lập trình
Phạm vi (scope) trong ngôn ngữ lập trình là một khái niệm
dùng để xác định một vùng của chương trình máy tính, mà trong đó, biến có tồn tại và có thể tham chiếu tới
nó để thực hiện các thao tác.
Trong JavaScript, phạm vi được xác định dựa trên mã nguồn (dựa
trên văn bản), nên được gọi là phạm vi dựa trên từ vựng (lexical scope).
Phạm vi của biến dựa trên từ vựng được gọi là lexical
variable scope.
Một vùng mã (code block) được xác định bằng các cặp dấu ngoặc
nhọn ({}). Trong các hàm, cặp dấu ngoặc nhọn (liền sau tên hàm) giúp phân định
phạm vi của một biến (khai báo bằng từ khóa var) là toàn cục (global) hay cục bộ
(local).
Phạm vi cục bộ, biến được khai báo bên trong hàm, nên chỉ tồn
tại ở trong hàm:
function TeoFunction(){
var x = 3;
console.log("x trong ham: " + x);
}
TeoFunction(); // x trong ham: 3
console.log("x ngoai ham: " + x); // báo lỗi, x is not defined
Phạm vi toàn cục, biến được khai báo ngoài hàm, nên có thể
truy cập ở bên trong các hàm khác nhau, hay mọi vị trí trong trang mã nguồn:
var x = 3;
function TeoFunction(){
console.log("x trong ham: " + x);
}
TeoFunction(); // x trong ham: 3
console.log("x ngoai ham: " + x); // x ngoài hàm: 3
Ngoại lệ, biến được khai báo trong hàm nhưng không có từ
khóa var cũng được xem là biến toàn cục,
ví dụ:
function TiFunction(){
tiBien = "Cu Ti";
}
TiFunction(); // thực thi hàm để chạy lệnh khai báo
biến
console.log(tiBien); // Cu Ti
function TeoFunction(){
console.log("Teo chao " + tiBien);
}
TeoFunction(); // Teo chao Cu Ti
Trường hợp đã có biến toàn cục, bên trong hàm tiếp tục khai
báo một biến cục bộ trùng tên với biến toàn cục, JavaScript vẫn cho phép, khi
đó tồn tại hai biến trùng tên, một biến toàn cục và một biến cục bộ:
function TiFunction(){
tiBien = "Cu Ti";
}
TiFunction(); // thực thi hàm để chạy lệnh khai báo
biến
console.log(tiBien); // Cu Ti
function TeoFunction(){
var tiBien = "abc";
console.log("Teo chao " + tiBien);
}
TeoFunction(); // Teo chao abc
console.log(tiBien); // Cu Ti
Dùng từ khóa let để khai
báo biến
Như ở phần trước đã trình bày, trong JavaScript, nếu dùng từ khóa var để khai báo biến thì phạm vi của biến
được xác định bằng các hàm: khai báo trong hàm là cục bộ, khai báo ngoài hàm là
toàn cục. Như vậy, trong trường hợp cần xác lập phạm vi của biến theo các khối
lệnh, giới hạn bằng các cặp dấu ngoặc nhọn ({}), thì sẽ không thực hiện được với
từ khóa var. Ví dụ:
var topic = "JavaScript";
if(topic) {
var topic = "React";
console.log("trong vung if: ", topic); // trong vung if: React
}
console.log("ngoai vung if: ", topic); // ngoai vung if: React
Ở đoạn mã trên, biến topic
trong khối lệnh if đã thay đổi giá trị
của biến toàn cục topic nằm bên
ngoài.
Với ES6, bạn có thể sử dụng từ khóa let thay cho từ khóa var để khai báo biến, khi đó, phạm vi của biến sẽ được xác lập theo các khối lệnh nằm trong các cặp dấu ngoặc nhọn ({}), giúp bảo vệ giá trị của các biến toàn cục. Ví dụ:
var topic = "JavaScript";
if(topic) {
let topic = "React";
console.log("trong vung if: ", topic); // trong vung if: React
}
console.log("ngoai vung if: ", topic); // ngoai vung if: JavaScript
Một ví dụ khác về
tình huống sử dụng từ khóa var trong
vòng lặp for. Từ khóa var làm cho biến i trong vòng lặp for trở
thành biến toàn cục, làm cho chương trình không còn đúng.
var div,
container
=
document.getElementById("container");
for (var i = 0; i < 5; i++) {
div = document.createElement("div");
div.onclick = function() {
alert("Day la div thu: " + i);
};
container.appendChild(div);
}
Vòng lặp for ở đoạn
mã trên sẽ tạo ra 5 phần tử div đặt
trong container, mỗi phần tử div được gắn một sự kiện click, để khi người dùng bấm vào mỗi div thì nó sẽ bật lên một thông báo cho
biết số hiệu của phần tử div đó. Do từ
khóa var làm cho biến i thuộc kiểu toàn cục, nên sau khi vòng lặp
for chạy xong thì giá trị của biến i là 5, do vậy mọi phần tử đều có số hiệu
là 5.
Trong vòng lặp for,
nếu thay từ khóa var bằng từ khóa let thì biến i sẽ có phạm vi trong vòng lặp. Do vậy, khi bấm vào mỗi div thì nó sẽ có số hiệu từ 0 đến 4
tương ứng.
const container = document.getElementById('container');
let div;
for (let i = 0; i < 5; i++) {
div = document.createElement('div');
div.onclick = function() {
alert("Day la div thu: " + i);
}
container.appendChild(div);
}
1.1.2
Mẫu xuất chuỗi
Trong tiếng Anh, ba từ này là tương đương: template strings,
template literals và string templates tạm gọi là mẫu dùng để xuất chuỗi.
Thông thường, bạn hay sử dụng dấu cộng (+) để nối chuỗi với
giá trị của biến, ví dụ:
console.log('Ho ten la: ' + ho + ' ' + ten);
Ngoài cách trên, bạn có thể sử dụng mẫu (template) để xuất
chuỗi cùng với giá trị của biến, sử dụng cú pháp ${}.
Ví dụ:
console.log(`Ho ten la: ${ ho } ${ ten }`);
Để ý ở đoạn mã trên, đừng nhầm dấu nháy đơn (‘’) với dấu
(``).
Khi hiển thị template, các khoảng trắng và dấu xuống dòng vẫn
được duy trì so với mã nguồn, vì vậy rất tiện cho việc thiết kế các mẫu dữ liệu
xuất ra màn hình, như một email hoặc một đoạn mã nguồn minh họa.
Ví dụ:
const ten = 'Teo';
const qty = 4;
const email = `
Xin chao ban ${ ten },
Chung toi ra vui khi nhan duoc ${ qty } don hang tu ban.
Cam on ban.`;
console.log(email);
Hoặc bạn có thể sử dụng template để xuất trực tiếp trên
trang HTML như ví dụ sau:
const article = {
title: 'Xuat template',
body: 'Su dung template de xuat truc tiep len trang web'
};
document.body.innerHTML = `
<section>
<header>
<h1>Hoc React</h1>
</header>
<article>
<h2>${article.title}</h2>
${article.body}
</article>
<footer>
<p>copyright ${new Date().getFullYear()} | Hoc React</p>
</footer>
</section>
`;
1.1.3
Xem và đọc thêm
– Sử dụng các từ khóa sau để tìm kiếm trên mạng, đọc và xem
thêm: biến, phạm vi của biến, lexical variable scope,
– [1] Alex Banks, Eve Porcello, Learning React – Mordern Patterns
for Developing React Apps, O’Reilly Media, 2020, p7 – p11
– Phạm vi của biến: https://levunguyen.com/laptrinhjavascript/2021/02/12/su-dung-scope-trong-javascript/
– Phạm vi (tầm vực): https://vi.wikipedia.org/wiki/T%E1%BA%A7m_v%E1%BB%B1c_(khoa_h%E1%BB%8Dc_m%C3%A1y_t%C3%ADnh)
1.1.4
Bài tập và thực hành
Bài tập 1. Viết lại các đoạn mã trong phần lý thuyết để chạy
và kiểm tra lại kết quả.
Bài tập 2. Viết một trang web hoàn chỉnh, minh họa cho việc
sử dụng từ khóa var và let trong vòng lặp for (đã đề cập trong phần lý thuyết của bài học).
Gợi ý:
Bài tập 2: Viết một trang web hoàn chỉnh, minh họa cho việc
sử dụng từ khóa var và let trong vòng lặp for (đã đề cập trong
phần lý thuyết của bài học).
Minh họa cho trường hợp dùng từ khóa var:
[test.html]
<!DOCTYPE html>
<html>
<head>
<style>
div {
background-color: red;
height: 100px;
width: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<section id="container">
</section>
<script>
const container = document.getElementById("container");
var div;
for (var i = 0; i < 5; i++) {
div = document.createElement("div");
div.onclick = function() {
alert("This is box #: " + i);
};
container.appendChild(div);
}
</script>
</body>
</html>
1.1.5
Câu hỏi ôn tập
Câu 1. Trong JavaScript, câu lệnh console.log("Teo chao " + tiBien); trong đoạn mã sau sẽ
xuất ra nội dung gì?
function TiFunction(){
tiBien = "Cu Ti";
}
TiFunction();
console.log(tiBien);
function TeoFunction(){
var tiBien = "abc";
console.log("Teo chao " + tiBien);
}
A. Teo chao Cu Ti
B. Teo chao abc
C. null
D. Báo lỗi trùng tên biến
Câu 2. Trong JavaScript, để khai báo biến toàn cục, bạn sử dụng
cách nào?
A. khai báo ở trong hàm với từ khóa let
B. khai báo ở ngoài hàm
C. khai báo ở trong hàm với từ khóa var
D. khai báo trong khối lệnh (code block) với từ khóa var
Câu 3. Trong JavaScript, để khai báo biến cục bộ trong phạm
vi từng khối lệnh, sử dụng từ khóa nào?
A. const
B. let
C. var
D. không dùng từ khóa
Câu 4. Trong JavaScript, muốn tạo ra một biến mà không cho
phép thay đổi giá trị sau khi đã được khởi tạo giá trị ban đầu, thì dùng từ
khóa nào?
A. const
B. let
C. var
D. không dùng từ khóa
Câu 5. Thuật ngữ “mẫu xuất chuỗi”, trong tiếng Anh có tên gọi
là:
A. template strings
B. template literals
C. string templates
D. cả ba đáp án trên
Đáp án: 1 (B), 2 (B), 3 (B), 4 (A), 5 (D)
-----
Cập nhật: 26/2/2022
-----