JavaScript Nâng Cao - Kỳ 12
Có một câu nói vui là: Trên đời chỉ có thứ nhiều người chửi và thứ không ai thèm dùng.
Javascript là một ví dụ điển hình, nó có một số điểm thú vị nhưng cũng khiến chúng ta phải đau đầu. Lý thuyết thì dễ hiểu, nhưng khi thực hành là cả một vấn đề. Vậy nên, mình sẽ cùng các bạn đi sâu vào từng ví dụ cụ thể và phân tích, mổ xẻ nó để hiểu hơn về Javascript nhé.
Series này có thể sẽ khá dài mình không biết sẽ có bao nhiêu Kỳ tuy nhiên để tiện cho các bạn nào không đọc các bài trước đó của mình về JS thì trong loạt bài này mình sẽ giải thích lại toàn bộ. Các lý thuyết trong loạt bài này mình cũng có thể sẽ giải thích lại nhiều lần (tùy hứng) để các bạn có thể năm rõ nó hơn nhé.
Ok vào bài thôi nào... GÉT GÔ 🚀
Nếu có bất kỳ câu hỏi nào đừng ngại hãy bình luận dưới phần
comment
nhé. Hoặc chỉ cần để lại mộtcomment chào mình
là đã giúp mình có thêm động lực hoàn thành series này. Cảm ơn các bạn rất nhiều. 🤗
1. Set và các giá trị duy nhất
Output của đoạn code bên dưới là gì:
const set = new Set([1, 1, 2, 3, 4]);
console.log(set);
- A:
[1, 1, 2, 3, 4]
- B:
[1, 2, 3, 4]
- C:
{1, 1, 2, 3, 4}
- D:
{1, 2, 3, 4}
Đáp án của câu hỏi này là
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
Đáp án: D
Cùng mình đi tìm hiểu tại sao kết quả lại là như vậy nhé ❓️
1.1. Set trong JavaScript
Set
là một cấu trúc dữ liệu trong JavaScript được giới thiệu từ ES6. Nó cho phép bạn lưu trữ các giá trị duy nhất của bất kỳ kiểu dữ liệu nào, bao gồm cả các giá trị nguyên thủy và các tham chiếu đối tượng.
1.2. Đặc điểm của Set
-
Giá trị duy nhất: Mỗi giá trị trong Set chỉ có thể xuất hiện một lần. Nếu bạn thêm một giá trị đã tồn tại, nó sẽ bị bỏ qua.
-
Thứ tự chèn: Set giữ nguyên thứ tự chèn của các phần tử. Điều này có nghĩa là khi bạn lặp qua một Set, các phần tử sẽ được trả về theo thứ tự chúng được chèn vào.
-
Không có chỉ mục: Không giống như mảng, Set không có chỉ mục. Bạn không thể truy cập các phần tử bằng chỉ mục.
1.3. Phân tích đoạn code
Trong đoạn code của chúng ta:
const set = new Set([1, 1, 2, 3, 4]);
Chúng ta đang tạo một Set mới và khởi tạo nó với một mảng [1, 1, 2, 3, 4]
. Set sẽ tự động loại bỏ các giá trị trùng lặp. Trong trường hợp này, giá trị 1
xuất hiện hai lần trong mảng ban đầu, nhưng Set chỉ giữ lại một lần.
Khi chúng ta console.log(set)
, kết quả sẽ là {1, 2, 3, 4}
. Đây là cách JavaScript hiển thị một Set trong console. Nó sử dụng dấu ngoặc nhọn {}
thay vì dấu ngoặc vuông []
như mảng.
1.4. Ví dụ minh họa
Để hiểu rõ hơn, hãy xem xét một ví dụ khác:
const fruits = new Set(['apple', 'banana', 'apple', 'orange', 'banana']);
console.log(fruits); // Output: Set(3) { 'apple', 'banana', 'orange' }
// Thêm phần tử vào Set
fruits.add('mango');
fruits.add('apple'); // 'apple' đã tồn tại nên sẽ không được thêm vào
console.log(fruits); // Output: Set(4) { 'apple', 'banana', 'orange', 'mango' }
Trong ví dụ này, chúng ta thấy rằng Set tự động loại bỏ các giá trị trùng lặp ('apple' và 'banana'). Khi chúng ta thêm 'mango', nó được thêm vào Set. Tuy nhiên, khi chúng ta cố gắng thêm 'apple' lần nữa, Set vẫn giữ nguyên vì 'apple' đã tồn tại.
1.5. Tóm lại
Set là một cấu trúc dữ liệu hữu ích trong JavaScript khi bạn cần lưu trữ một tập hợp các giá trị duy nhất. Nó tự động xử lý việc loại bỏ các giá trị trùng lặp, giúp code của bạn gọn gàng và hiệu quả hơn trong nhiều trường hợp.
2. Import và Read-only Module
Output của đoạn code bên dưới là gì:
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
- A:
10
- B:
11
- C:
Error
- D:
NaN
Đáp án của câu hỏi này là
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
Đáp án: C
Cùng mình đi tìm hiểu tại sao kết quả lại là như vậy nhé ❓️
2.1. Module trong JavaScript
Modules là một tính năng quan trọng trong JavaScript hiện đại, cho phép chúng ta chia nhỏ code thành các phần riêng biệt, dễ quản lý và tái sử dụng. Tuy nhiên, cách modules hoạt động có một số đặc điểm quan trọng mà chúng ta cần lưu ý.
2.2. Import và Read-only
Khi chúng ta import một giá trị từ một module khác, giá trị đó được coi là read-only (chỉ đọc). Điều này có nghĩa là chúng ta không thể trực tiếp thay đổi giá trị đã import.
Trong ví dụ của chúng ta:
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";
myCounter += 1; // Lỗi!
console.log(myCounter);
Khi chúng ta cố gắng thay đổi giá trị của myCounter
, JavaScript sẽ throw một Error. Cụ thể, nó sẽ là một TypeError
với thông báo như "Assignment to constant variable" hoặc tương tự.
2.3. Tại sao lại như vậy?
Đây là một tính năng bảo vệ trong hệ thống module của JavaScript. Nó ngăn chặn các module khác vô tình hoặc cố ý thay đổi trạng thái của module được import, giúp đảm bảo tính nhất quán và dễ dự đoán của code.
2.4. Làm thế nào để thay đổi giá trị?
Nếu bạn muốn thay đổi giá trị của một biến được export, bạn nên export một function để thay đổi giá trị đó. Ví dụ:
// counter.js
let counter = 10;
export function incrementCounter() {
counter += 1;
return counter;
}
export default counter;
// index.js
import myCounter, { incrementCounter } from "./counter";
console.log(myCounter); // 10
console.log(incrementCounter()); // 11
console.log(myCounter); // Vẫn là 10!
Trong ví dụ này, myCounter
vẫn giữ nguyên giá trị ban đầu, nhưng chúng ta có thể thay đổi giá trị của counter
trong module gốc thông qua function incrementCounter
.
2.5. Tóm lại
Hiểu về tính chất read-only của các giá trị được import là rất quan trọng khi làm việc với modules trong JavaScript. Nó giúp chúng ta tránh được nhiều lỗi tiềm ẩn và viết code an toàn, dễ bảo trì hơn. Khi cần thay đổi giá trị từ một module khác, hãy nhớ sử dụng các function được export thay vì cố gắng thay đổi trực tiếp giá trị đã import.
3. Phép toán delete trong JavaScript
Output của đoạn code bên dưới là gì:
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);
- A:
false
,true
- B:
"Lydia"
,21
- C:
true
,true
- D:
undefined
,undefined
Đáp án của câu hỏi này là
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
Đáp án: A
Cùng mình đi tìm hiểu tại sao kết quả lại là như vậy nhé ❓️
3.1. Phép toán delete trong JavaScript
Phép toán delete
trong JavaScript được sử dụng để xóa một thuộc tính khỏi một đối tượng. Điều quan trọng cần nhớ là:
delete
trả vềtrue
nếu xóa thành công hoặc nếu thuộc tính không tồn tại.delete
trả vềfalse
nếu không thể xóa thuộc tính (ví dụ: thuộc tính không thể xóa được).delete
không ảnh hưởng đến các biến được khai báo bằngvar
,let
, hoặcconst
.
3.2. Phân tích đoạn code
Trong đoạn code của chúng ta:
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);
3.2.1. Trường hợp của name
name
được khai báo bằng const
, do đó nó không thể bị xóa bởi phép toán delete
. Vì vậy, delete name
sẽ trả về false
.
3.2.2. Trường hợp của age
age
được khai báo mà không sử dụng var
, let
, hoặc const
. Trong trường hợp này, JavaScript sẽ tự động tạo một thuộc tính trên đối tượng toàn cục (global object). Trong môi trường trình duyệt, đối tượng toàn cục là window
.
Vì age
là một thuộc tính của đối tượng toàn cục, nó có thể bị xóa bởi phép toán delete
. Do đó, delete age
sẽ trả về true
.
3.3. Ví dụ minh họa
Để hiểu rõ hơn, hãy xem xét ví dụ sau:
const obj = {x: 1, y: 2};
let z = 3;
console.log(delete obj.x); // true
console.log(delete obj.y); // true
console.log(delete z); // false
console.log(obj); // {}, z vẫn là 3
Trong ví dụ này:
delete obj.x
vàdelete obj.y
trả vềtrue
vì chúng xóa thành công các thuộc tính của đối tượng.delete z
trả vềfalse
vìz
là một biến được khai báo bằnglet
, không thể bị xóa bởidelete
.
3.4. Tóm lại
Phép toán delete
trong JavaScript chỉ có tác dụng với các thuộc tính của đối tượng. Nó không thể xóa các biến được khai báo bằng var
, let
, hoặc const
. Khi sử dụng delete
, hãy nhớ rằng nó trả về giá trị boolean chỉ ra liệu việc xóa có thành công hay không, chứ không phải giá trị của thuộc tính bị xóa.
4. Destructuring trong JavaScript
Output của đoạn code bên dưới là gì:
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
console.log(y);
- A:
[[1, 2, 3, 4, 5]]
- B:
[1, 2, 3, 4, 5]
- C:
1
- D:
[1]
Đáp án của câu hỏi này là
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
Đáp án: C
Cùng mình đi tìm hiểu tại sao kết quả lại là như vậy nhé ❓️
4.1. Destructuring trong JavaScript
Destructuring là một cú pháp trong JavaScript cho phép chúng ta "giải nén" các giá trị từ mảng hoặc thuộc tính từ đối tượng vào các biến riêng biệt. Đây là một tính năng mạnh mẽ giúp code trở nên ngắn gọn và dễ đọc hơn.
4.2. Array Destructuring
Trong trường hợp của chúng ta, chúng ta đang sử dụng array destructuring:
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
Cú pháp [y]
ở đây có nghĩa là:
- Lấy phần tử đầu tiên của mảng
numbers
và gán nó cho biếny
.
4.3. Phân tích kết quả
Vì y
được gán giá trị của phần tử đầu tiên trong mảng numbers
, nên y
sẽ có giá trị là 1
.
Khi chúng ta console.log(y)
, kết quả sẽ là 1
.
4.4. Ví dụ mở rộng
Để hiểu rõ hơn về array destructuring, hãy xem xét một vài ví dụ khác:
const colors = ['red', 'green', 'blue'];
// Lấy phần tử đầu tiên
const [firstColor] = colors;
console.log(firstColor); // 'red'
// Lấy phần tử thứ hai và thứ ba
const [, secondColor, thirdColor] = colors;
console.log(secondColor, thirdColor); // 'green' 'blue'
// Sử dụng rest operator
const [primary, ...secondaryColors] = colors;
console.log(primary); // 'red'
console.log(secondaryColors); // ['green', 'blue']
4.5. Tóm lại
Array destructuring là một cách tiện lợi để trích xuất giá trị từ mảng trong JavaScript. Nó cho phép chúng ta gán các giá trị của mảng vào các biến một cách nhanh chóng và dễ đọc. Trong ví dụ của chúng ta, [y]
lấy phần tử đầu tiên của mảng numbers
, do đó y
có giá trị là 1
.
5. Spread Operator trong JavaScript
Output của đoạn code bên dưới là gì:
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };
console.log(admin);
- A:
{ admin: true, user: { name: "Lydia", age: 21 } }
- B:
{ admin: true, name: "Lydia", age: 21 }
- C:
{ admin: true, user: ["Lydia", 21] }
- D:
{ admin: true }
Đáp án của câu hỏi này là
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
↓↓↓↓↓↓↓↓↓↓
Đáp án: B
Cùng mình đi tìm hiểu tại sao kết quả lại là như vậy nhé ❓️
5.1. Spread Operator trong JavaScript
Spread Operator (...
) là một tính năng mạnh mẽ trong JavaScript, được giới thiệu từ ES6. Nó cho phép chúng ta "trải" (spread) các phần tử của một đối tượng có thể lặp lại (như mảng hoặc đối tượng) thành các phần tử riêng lẻ.
5.2. Sử dụng Spread Operator với Objects
Khi sử dụng Spread Operator với objects, nó sẽ sao chép tất cả các cặp key-value của object đó vào object mới.
Trong trường hợp của chúng ta:
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };
Spread Operator ...user
sẽ "trải" tất cả các thuộc tính của user
vào object admin
.
5.3. Phân tích kết quả
Kết quả của console.log(admin)
sẽ là:
{ admin: true, name: "Lydia", age: 21 }
Điều này xảy ra vì:
admin: true
được thêm vào objectadmin
....user
"trải" các thuộc tính củauser
(name
vàage
) vào objectadmin
.
5.4. Ví dụ mở rộng
Để hiểu rõ hơn về Spread Operator với objects, hãy xem xét một vài ví dụ khác:
// Kết hợp nhiều objects
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const combined = { ...obj1, ...obj2 };
console.log(combined); // { a: 1, b: 2, c: 3, d: 4 }
// Ghi đè thuộc tính
const defaultSettings = { theme: 'light', fontSize: 12 };
const userSettings = { ...defaultSettings, theme: 'dark' };
console.log(userSettings); // { theme: 'dark', fontSize: 12 }
// Thêm thuộc tính mới
const base = { x: 10, y: 20 };
const extended = { ...base, z: 30 };
console.log(extended); // { x: 10, y: 20, z: 30 }
5.5. Tóm lại
Spread Operator là một công cụ mạnh mẽ trong JavaScript để làm việc với objects và arrays. Khi sử dụng với objects, nó cho phép chúng ta dễ dàng sao chép và kết hợp các thuộc tính từ nhiều objects khác nhau. Trong ví dụ của chúng ta, nó giúp tạo ra một object mới admin
bao gồm cả thuộc tính admin: true
và tất cả các thuộc tính của object user
.
Nếu có bất kỳ câu hỏi nào đừng ngại hãy bình luận dưới phần
comment
nhé. Hoặc chỉ cần để lại mộtcomment chào mình
là đã giúp mình có thêm động lực hoàn thành series này. Cảm ơn các bạn rất nhiều. 🤗
All rights reserved