??
)Tóm cái váy lại!
Phần 3 sẽ đào sâu vào một số khái niệm cốt lõi khác của JavaScript: giá trị Truthy và Falsy, các loại toán tử và biểu thức phổ biến, cùng với hai toán tử cực kỳ hữu ích là toán tử ba ngôi và toán tử Nullish Coalescing (??
). Mấy cái này tuy cơ bản nhưng nắm vững thì code sẽ gọn gàng và hiệu quả hơn nhiều đó!
Trong JavaScript, không phải mọi giá trị đều là true
hoặc false
một cách tường minh, nhưng chúng có thể được “ép” thành boolean trong các ngữ cảnh logic (ví dụ: trong câu lệnh if
). Những giá trị được coi là false
trong ngữ cảnh logic được gọi là falsy, còn lại là truthy.
Các giá trị Falsy phổ biến:
false
(dĩ nhiên rồi!)0
(số không)-0
(số không âm)0n
(BigInt không)""
(chuỗi rỗng)null
undefined
NaN
(Not a Number)Tất cả các giá trị khác đều là Truthy, bao gồm:
"hello"
, "0"
, "false"
)1
, -1
, 0.5
)[]
){}
)function() {}
)true
Hiểu rõ truthy/falsy giúp viết các điều kiện ngắn gọn hơn.
<div id="truthy-falsy-output"></div>
<script>
const outputDiv = document.getElementById('truthy-falsy-output');
let output = '';
function checkTruthyFalsy(value, name) {
if (value) {
output += `<p>Giá trị <strong>${name}</strong> (${JSON.stringify(
value
)}) là <strong>Truthy</strong></p>`;
} else {
output += `<p>Giá trị <strong>${name}</strong> (${JSON.stringify(
value
)}) là <strong>Falsy</strong></p>`;
}
}
checkTruthyFalsy(false, 'false'); // Falsy
checkTruthyFalsy(0, '0'); // Falsy
checkTruthyFalsy('', '""'); // Falsy
checkTruthyFalsy(null, 'null'); // Falsy
checkTruthyFalsy(undefined, 'undefined'); // Falsy
checkTruthyFalsy(NaN, 'NaN'); // Falsy
output += '<hr>'; // Phân cách
checkTruthyFalsy(true, 'true'); // Truthy
checkTruthyFalsy(1, '1'); // Truthy
checkTruthyFalsy('hello', '"hello"'); // Truthy
checkTruthyFalsy([], '[]'); // Truthy
checkTruthyFalsy({}, '{}'); // Truthy
checkTruthyFalsy(function () {}, 'function(){}'); // Truthy
checkTruthyFalsy('0', '"0"'); // Truthy
checkTruthyFalsy('false', '"false"'); // Truthy
outputDiv.innerHTML = output;
</script>
Toán tử là các ký hiệu đặc biệt dùng để thực hiện các phép toán, so sánh, gán giá trị, hoặc các thao tác logic trên các giá trị (gọi là toán hạng - operands).
Một số nhóm toán tử phổ biến:
Toán tử số học (Arithmetic Operators): Dùng cho các phép tính toán học.
+
(Cộng): 5 + 3
kết quả là 8
. Cũng dùng để nối chuỗi: "Hello" + " World"
là "Hello World"
.-
(Trừ): 10 - 4
kết quả là 6
.*
(Nhân): 6 * 7
kết quả là 42
.**
(Lũy thừa - ES7): 2 ** 3
kết quả là 8
(2 mũ 3)./
(Chia): 10 / 2
kết quả là 5
.%
(Chia lấy dư - Modulo): 10 % 3
kết quả là 1
.++
(Tăng lên 1): let a = 5; a++;
thì a
thành 6
.--
(Giảm đi 1): let b = 5; b--;
thì b
thành 4
.Toán tử gán (Assignment Operators): Dùng để gán giá trị cho biến.
=
(Gán): let x = 10;
+=
(Cộng rồi gán): x += 5;
tương đương x = x + 5;
-=
(Trừ rồi gán): x -= 3;
tương đương x = x - 3;
*=
(Nhân rồi gán): x *= 2;
tương đương x = x * 2;
/=
(Chia rồi gán): x /= 4;
tương đương x = x / 4;
%=
(Chia lấy dư rồi gán): x %= 3;
tương đương x = x % 3;
**=
(Lũy thừa rồi gán): x **= 2;
tương đương x = x ** 2;
Toán tử so sánh (Comparison Operators): Dùng để so sánh hai giá trị, kết quả trả về là true
hoặc false
.
==
(Bằng - Loose Equality): So sánh giá trị sau khi đã cố gắng chuyển đổi kiểu dữ liệu. Ví dụ: 5 == "5"
là true
. Nên hạn chế dùng!!=
(Không bằng - Loose Inequality): 5 != "5"
là false
.===
(Bằng tuyệt đối - Strict Equality): So sánh cả giá trị và kiểu dữ liệu, không chuyển đổi kiểu. Ví dụ: 5 === "5"
là false
. Nên dùng cái này!!==
(Không bằng tuyệt đối - Strict Inequality): 5 !== "5"
là true
.>
(Lớn hơn): 10 > 5
là true
.<
(Nhỏ hơn): 10 < 5
là false
.>=
(Lớn hơn hoặc bằng): 10 >= 10
là true
.<=
(Nhỏ hơn hoặc bằng): 10 <= 5
là false
.Toán tử logic (Logical Operators): Dùng để kết hợp các biểu thức logic.
&&
(Và - AND): expr1 && expr2
trả về expr1
nếu nó là falsy, ngược lại trả về expr2
. Thường dùng để kiểm tra cả hai điều kiện đều đúng: (age > 18) && (hasLicense)
||
(Hoặc - OR): expr1 || expr2
trả về expr1
nếu nó là truthy, ngược lại trả về expr2
. Thường dùng để kiểm tra ít nhất một điều kiện đúng: isWeekend || isHoliday
!
(Phủ định - NOT): !expr
đảo ngược giá trị boolean của expr
. !true
là false
, !false
là true
. !0
là true
, !"hello"
là false
.Ngoài ra còn nhiều loại toán tử khác như: toán tử bitwise, toán tử chuỗi (+
), toán tử điều kiện (ba ngôi - xem dưới), toán tử typeof, toán tử instanceof, v.v.
Biểu thức là một đoạn code tạo ra một giá trị. Nó có thể là sự kết hợp của các giá trị (literals), biến, toán tử và lời gọi hàm.
Ví dụ về biểu thức:
5
(Một giá trị literal là một biểu thức)x
(Một biến là một biểu thức)x + 5
(Kết hợp biến, toán tử, literal)calculateArea(width, height)
(Một lời gọi hàm trả về giá trị)isLoggedIn && user.isAdmin
(Kết hợp biến và toán tử logic)Biểu thức được sử dụng ở bất cứ đâu mà JavaScript mong đợi một giá trị, ví dụ như bên phải phép gán, trong tham số hàm, trong câu lệnh if
, return
, v.v.
<div id="operators-output"></div>
<script>
let a = 10;
let b = 4;
let name = 'Duong';
let age = 30;
let output = '';
output += `<p>a = ${a}, b = ${b}</p>`;
output += `<p>a + b = ${a + b}</p>`; // 14
output += `<p>a % b = ${a % b}</p>`; // 2
a += b; // a = a + b = 10 + 4 = 14
output += `<p>Sau khi a += b, a = ${a}</p>`; // 14
output += `<p>age > 18 ? ${age > 18}</p>`; // true
output += `<p>name === "Duong" ? ${name === 'Duong'}</p>`; // true
output += `<p>b === "4" ? ${b === '4'}</p>`; // false (Strict equality)
output += `<p>b == "4" ? ${b == '4'}</p>`; // true (Loose equality - nên tránh)
output += `<p>!(age < 18) ? ${!(age < 18)}</p>`; // true
document.getElementById('operators-output').innerHTML = output;
</script>
Toán tử 3 ngôi là cách viết tắt cho câu lệnh if...else
đơn giản. Nó đặc biệt hữu ích khi bạn muốn gán giá trị cho biến hoặc trả về giá trị dựa trên một điều kiện.
Cú pháp:
condition ? value_if_true : value_if_false;
condition
: Biểu thức điều kiện được đánh giá (sẽ thành truthy hoặc falsy).value_if_true
: Giá trị được trả về nếu condition
là truthy.value_if_false
: Giá trị được trả về nếu condition
là falsy.<div id="ternary-output"></div>
<script>
let userAge = 20;
let canVote =
userAge >= 18 ? 'Được phép bỏ phiếu' : 'Chưa được phép bỏ phiếu';
let price = 100;
let discount = price > 50 ? 10 : 0; // Giảm 10 nếu giá > 50, ngược lại không giảm
let finalPrice = price - discount;
document.getElementById('ternary-output').innerHTML = `
<p>Tuổi ${userAge}: ${canVote}</p>
<p>Giá gốc: ${price}, Giảm giá: ${discount}, Giá cuối: ${finalPrice}</p>
`;
</script>
Toán tử 3 ngôi giúp code ngắn gọn hơn nhiều so với viết if...else
đầy đủ cho các trường hợp đơn giản. Tuy nhiên, lạm dụng nó cho các logic phức tạp có thể làm code khó đọc hơn.
??
)Toán tử Nullish Coalescing (??
) là một toán tử logic mới được giới thiệu trong ES2020. Nó trả về toán hạng bên phải (operand2
) chỉ khi toán hạng bên trái (operand1
) là null
hoặc undefined
. Ngược lại, nó trả về toán hạng bên trái.
Cú pháp:
operand1 ?? operand2;
Điểm khác biệt chính so với toán tử OR (||
):
||
trả về toán hạng bên phải nếu toán hạng bên trái là bất kỳ giá trị falsy nào (false
, 0
, ""
, null
, undefined
, NaN
).??
chỉ trả về toán hạng bên phải nếu toán hạng bên trái là null
hoặc undefined
. Nó coi 0
, ""
, và false
là các giá trị hợp lệ và sẽ trả về chúng nếu chúng xuất hiện ở bên trái.Điều này làm cho ??
trở nên cực kỳ hữu ích khi bạn muốn cung cấp giá trị mặc định cho một biến có thể là null
hoặc undefined
, nhưng bạn vẫn muốn chấp nhận các giá trị falsy khác như 0
hoặc ""
.
<div id="nullish-output"></div>
<script>
let output = '';
function checkOperator(val, name) {
let resultOR = val || 'Default Value (OR)';
let resultNullish = val ?? 'Default Value (Nullish)';
output += `
<tr>
<td><strong>${name}</strong> (${JSON.stringify(val)})</td>
<td>${JSON.stringify(resultOR)}</td>
<td>${JSON.stringify(resultNullish)}</td>
</tr>
`;
}
output += `
<table>
<thead>
<tr>
<th>Input Value</th>
<th>Result with ||</th>
<th>Result with ??</th>
</tr>
</thead>
<tbody>
`;
checkOperator(null, 'null'); // OR: Default, Nullish: Default
checkOperator(undefined, 'undefined'); // OR: Default, Nullish: Default
checkOperator(0, '0'); // OR: Default, Nullish: 0
checkOperator('', '""'); // OR: Default, Nullish: ""
checkOperator(false, 'false'); // OR: Default, Nullish: false
checkOperator('Hello', '"Hello"'); // OR: "Hello", Nullish: "Hello"
checkOperator(NaN, 'NaN'); // OR: Default, Nullish: NaN (NaN cũng không phải null/undefined)
output += `
</tbody>
</table>
`;
document.getElementById('nullish-output').innerHTML = output;
</script>
<style>
#nullish-output table {
border-collapse: collapse;
width: 100%;
}
#nullish-output th,
#nullish-output td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
}
#nullish-output th {
background-color: #f2f2f2;
}
</style>
Như bạn thấy, ??
rất hữu ích khi bạn muốn gán giá trị mặc định nhưng vẫn coi 0
, ""
, hoặc false
là các giá trị đầu vào hợp lệ.
Hiểu rõ về truthy/falsy giúp chúng ta viết các điều kiện logic ngắn gọn hơn. Nắm vững các toán tử cơ bản là nền tảng để thực hiện mọi thao tác trong JavaScript. Toán tử ba ngôi (? :
) và Nullish Coalescing (??
) là những công cụ mạnh mẽ giúp code sạch sẽ và dễ đọc hơn khi xử lý các điều kiện đơn giản và gán giá trị mặc định.
Ở phần tiếp theo, có thể chúng ta sẽ bàn về các cấu trúc điều khiển như if...else
, switch
, và các loại vòng lặp. Hẹn gặp lại các bạn! (Nếu mình không lười :D)