JavaScript Nâng Cao - Kỳ 29: Khám Phá Tham Chiếu, Kế Thừa và Ý Nghĩa Của Mảng
Giới Thiệu
Có một câu nói vui như thế này: "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 cho điều này. Mặc dù nó có nhiều tính năng thú vị, nhưng cũng có nhiều khía cạnh gây đau đầu cho lập trình viên. Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu một cách chi tiết qua những ví dụ cụ thể để làm rõ hơn về Javascript.
Series này là một hành trình dài, và mình không chắc nó sẽ kéo dài bao lâu. Tuy nhiên, để giúp các bạn dễ dàng theo dõi, mình sẽ giải thích lại các lý thuyết trong bài một cách tỉ mỉ nhất, và có thể sẽ tái giải thích nhiều lần để bạn có thể nắm vững kiến thức hơn.
Vậy thì chúng ta hãy bắt đầu! GÉT GÔ 🚀
Nếu bạn có bất kỳ câu hỏi nào, hãy đừng ngần ngại bình luận dưới bài viết này nhé. Hoặc chỉ cần để lại một bình luận chào mình cũng đã là động lực lớn để mình hoàn thành series này. Cảm ơn các bạn rất nhiều. 🤗
1. Tham Chiếu và Giá Trị Mặc Định Trong Hàm
Ví dụ 1:
Hãy xem đoạn code dưới đây và cho biết output của nó là gì:
javascript
const person = {
name: "Lydia Hallie",
hobbies: ["coding"]
};
function addHobby(hobby, hobbies = person.hobbies) {
hobbies.push(hobby);
return hobbies;
}
addHobby("running", []);
addHobby("dancing");
addHobby("baking", person.hobbies);
console.log(person.hobbies);
- A:
['coding']
- B:
['coding', 'dancing']
- C:
['coding', 'dancing', 'baking']
- D:
['coding', 'running', 'dancing', 'baking']
Đáp Án:
Đáp án của câu hỏi này là: C - ['coding', 'dancing', 'baking']
.
Phân Tích Chi Tiết:
Để hiểu rõ lý do đằng sau đáp án này, chúng ta phân tích từng lời gọi hàm addHobby
:
-
Lời gọi
addHobby("running", [])
:- Mảng rỗng được truyền vào hàm, do đó "running" được thêm vào mảng rỗng này, nhưng không ảnh hưởng đến
person.hobbies
.
- Mảng rỗng được truyền vào hàm, do đó "running" được thêm vào mảng rỗng này, nhưng không ảnh hưởng đến
-
Lời gọi `addHobby("dancing"):
- Không có đối số thứ hai, hàm sử dụng giá trị mặc định
person.hobbies
, và "dancing" được thêm vàoperson.hobbies
.
- Không có đối số thứ hai, hàm sử dụng giá trị mặc định
-
Lời gọi
addHobby("baking", person.hobbies)
:- Trực tiếp truyền
person.hobbies
, do đó "baking" cũng được thêm vào mảng này.
- Trực tiếp truyền
Kết quả cuối cùng là: person.hobbies
sẽ chứa: ['coding', 'dancing', 'baking']
.
2. Kế Thừa và Constructor Trong Class
Ví dụ 2:
Xem đoạn code dưới đây:
javascript
class Bird {
constructor() {
console.log("I'm a bird. 🦢");
}
}
class Flamingo extends Bird {
constructor() {
console.log("I'm pink. 🌸");
super();
}
}
const pet = new Flamingo();
- A:
I'm pink. 🌸
- B:
I'm pink. 🌸 I'm a bird. 🦢
- C:
I'm a bird. 🦢 I'm pink. 🌸
- D: Nothing, we didn't call any method
Đáp Án:
Đáp án là: B - I'm pink. 🌸 I'm a bird. 🦢
Phân Tích:
- Khi tạo một instance mới của
Flamingo
, constructor củaFlamingo
được gọi, in ra "I'm pink. 🌸". - Sau đó,
super()
được gọi, thực hiện constructor của lớp cha (Bird), và in ra "I'm a bird. 🦢".
Do đó, kết quả in ra là:
- "I'm pink. 🌸"
- "I'm a bird. 🦢"
3. Thao Tác Với Mảng và Hằng Số
Ví dụ 3:
Câu lệnh nào sẽ gây ra lỗi dưới đây:
javascript
const emojis = ["🎄", "🎅🏼", "🎁", "⭐"];
/* 1 */ emojis.push("🦌");
/* 2 */ emojis.splice(0, 2);
/* 3 */ emojis = [...emojis, "🥂"];
/* 4 */ emojis.length = 0;
- A: 1
- B: 1 và 2
- C: 3 và 4
- D: 3
Đáp Án:
Đáp án là: D
Giải Thích:
Dựa trên cách mà const
hoạt động với các mảng:
- Câu lệnh 1 và 2 không gây lỗi vì chúng chỉ thay đổi nội dung của mảng, không gán lại.
- Câu lệnh 3 sẽ gây ra lỗi vì nó cố gắng gán lại giá trị cho
emojis
. Điều này không cho phép với biến được khai báo bằngconst
. - Câu lệnh 4 thì hợp lệ vì nó chỉ thay đổi thuộc tính
length
của mảng mà không gán lại.
4. Iterator và Symbol.iterator
Ví dụ 4:
Ta cần định nghĩa gì vào object person
để khi gọi [...person]
sẽ cho kết quả là ['Lydia Hallie', 21]
?
javascript
const person = {
name: "Lydia Hallie",
age: 21
}
[...person] // ['Lydia Hallie', 21]
- A: Nothing, object are iterable by default
- B:
*[Symbol.iterator]() { for (let x in this) yield* this[x] }
- C:
*[Symbol.iterator]() { for (let x in this) yield* Object.values(this) }
- D:
*[Symbol.iterator]() { for (let x in this) yield this }
Đáp Án:
Đáp án là: C
Phân Tích:
- Để khiến một object trở nên có thể lặp (iterable), ta cần định nghĩa phương thức
Symbol.iterator
. - Phương thức này sẽ trả về một iterator object, thường được tạo bằng một generator function, sử dụng
yield
để trả về các giá trị. - Đáp án C là chính xác khi sử dụng
yield* Object.values(this)
để lấy tất cả giá trị của object.
5. Truthy và Falsy Trong JavaScript
Ví dụ 5:
Output của đoạn mã dưới đây sẽ là gì:
javascript
let count = 0;
const nums = [0, 1, 2, 3];
nums.forEach(num => {
if (num) count += 1;
})
console.log(count);
- A: 1
- B: 2
- C: 3
- D: 4
Đáp Án:
Đáp án là: C - 3
Phân Tích:
- Trong mảng
nums
, chỉ có số 0 là falsy, còn lại (1, 2, 3) đều là truthy. - Với mỗi phần tử, nếu nó là truthy, câu lệnh
count += 1
sẽ được thực thi. - Kết quả cuối cùng sẽ là 3 sau khi lặp qua tất cả các phần tử.
Hy vọng qua bài viết này, bạn đã hiểu rõ hơn về các chủ đề liên quan đến tham chiếu, kế thừa, mảng và nhiều khái niệm khác trong JavaScript. Nếu bạn có bất kỳ câu hỏi nào, hãy comment phía dưới nhé! Hẹn gặp lại bạn trong các kỳ sau của series JavaScript Nâng Cao!
source: viblo