Lesson 0.5.4 — Parameters
0. Metadata
| Field | Value |
|---|---|
| Stage | 0 — JavaScript Language Foundation |
| Module | 0.5 — Functions |
| Lesson | 0.5.4 |
| Competency | C01.5 — Functions |
| Depth Target | L2–L3 |
| Prerequisites | Arrow Functions (0.5.3), Destructuring (0.6.7), Arrays (0.6.2) |
| Estimated Cognitive Load | Medium–High |
1. Why This Exists (Vì sao cần học)
Bạn đã viết được function nhận tham số:
function greet(name) {
return "Hello " + name;
}Nhưng trong thực tế, caller không lúc nào cũng truyền đủ giá trị:
greet(); // "Hello undefined"
greet(null); // "Hello null"
greet(""); // "Hello "Vấn đề cốt lõi
Function cần linh hoạt để xử lý input thiếu, input dư, hoặc input có cấu trúc phức tạp. Nếu bạn chỉ dùng parameter đơn giản, code bên trong function sẽ tràn ngập if kiểm tra undefined, hoặc bạn phải thủ công gom các argument thừa thành array.
JavaScript cung cấp 3 công cụ để giải quyết: default parameters (điền giá trị mặc định), rest parameters (gom argument dư), và parameter destructuring (tách cấu trúc ngay tại cửa vào).
Nếu không nắm vững 3 công cụ này, bạn sẽ viết code dài dòng, dễ lỗi, và không tận dụng được API hiện đại (ví dụ: React props destructuring, Node.js options object).
2. Prerequisites (Yêu cầu đầu vào)
Trước khi học bài này, bạn cần:
- Viết được function declaration, expression, và arrow function (0.5.1–0.5.3).
- Hiểu
undefinedlà một primitive value riêng biệt (0.2.3). - Biết object và array ở mức cơ bản: tạo, truy cập property, index (0.2.4).
- Biết
const/letvà block scope cơ bản (0.2.2).
WARNING
Nếu bạn chưa chắc function greet(name) { return name; } hoạt động thế nào, quay lại 0.5.1 trước. Bài này mở rộng parameter từ cơ bản sang linh hoạt hơn.
INFO
Parameter destructuring trong bài này là lần đầu tiên cú pháp destructuring xuất hiện trong khóa học. Bạn sẽ học cú pháp này ở dạng parameter-specific, rồi đào sâu hơn ở 0.6.7.
3. Learning Objectives (Mục tiêu học tập)
Sau bài này, bạn có thể:
- Viết default parameter để xử lý argument bị thiếu hoặc là
undefined. - Viết rest parameter để gom các argument còn lại thành một array.
- Viết parameter destructuring cho object và array.
- Dự đoán giá trị của parameter khi argument là
null,0,"", hoặcundefined. - Phân biệt rest parameter (
...args) vàargumentsobject ở mức awareness.
4. Mental Model (Mô hình tư duy)
Hãy hình dung parameter list như một băng chuyền tiếp nhận hàng hóa:
Caller gửi: [box1] [box2] [box3] [box4] ...
↓
Parameter slots: slot1 slot2 ...rest
↓
Default values: nếu slot trống → điền giá trị mặc định
↓
Destructuring: mở hộp ngay tại băng chuyền, lấy từng món bên trongMental Model
Arguments (từ caller)
↓
Parameter Slots
↓
├─ Default? → Nếu argument === undefined, dùng default
├─ Rest? → Gom mọi thứ còn lại vào một array
└─ Destructure? → Mở cấu trúc object/array ngay tại slot
↓
Local bindings sẵn sàng trong function bodyQuan trọng: Default chỉ kích hoạt khi argument là undefined, không phải bất kỳ falsy value nào. null, 0, "" đều là giá trị hợp lệ và sẽ chiếm slot.
5. Core Concepts (Các khái niệm cốt lõi)
Essential (Bắt buộc)
| Concept | Ý nghĩa |
|---|---|
| Default Parameter | function fn(x = 10) — nếu x nhận undefined, dùng 10. |
| Rest Parameter | function fn(...args) — gom mọi argument còn lại thành array args. |
| Parameter Destructuring | function fn({ name }) — tách property name từ object argument ngay tại parameter. |
| Undefined trigger | Default chỉ trigger bởi undefined, không phải null hay 0. |
Supporting (Hỗ trợ)
| Concept | Ý nghĩa |
|---|---|
| Default với expression | function fn(x = getDefault()) — expression được evaluate khi cần. |
| Rest phải ở cuối | function fn(a, ...rest, b) là SyntaxError. |
| Destructuring + default | function fn({ name = "Guest" }) — kết hợp cả hai. |
| Nested destructuring | function fn({ user: { name } }) — tách lồng nhau. |
Awareness (Biết tồn tại)
| Concept | Lý do chưa đào sâu |
|---|---|
arguments object | Legacy way để truy cập tất cả args. Không dùng trong modern code; cơ chế thuộc Stage 1. |
arguments vs rest | arguments không phải real array, không có map. Rest parameter thay thế hoàn toàn. |
Out of Scope (Không thuộc bài này)
argumentsobject deep dive (Stage 1)- Parameter evaluation order / TDZ (Stage 1)
- Generator function parameters (Stage 3)
- Decorator / parameter annotation (Stage 6 — TypeScript)
6. Worked Example (Ví dụ phân tích từng bước)
Xét đoạn code sau:
function createUser({ name, role = "user", ...prefs } = {}) {
return {
name: name ?? "Anonymous",
role,
preferences: prefs
};
}
const u1 = createUser({ name: "An", theme: "dark", lang: "vi" });
const u2 = createUser();
const u3 = createUser({ name: null, role: null });Walkthrough
Step 1 — Parameter Destructuring{ name, role = "user", ...prefs } nghĩa là: JavaScript mong đợi argument đầu tiên là một object. Nó tách:
name— binding localrole— binding local, default"user"nếuundefined...prefs— rest: mọi property còn lại (theme,lang)
Step 2 — Default cho chính object= {} ở cuối nghĩa là: nếu argument hoàn toàn bị thiếu (undefined), dùng object rỗng {}. Nếu không có = {}, dòng createUser() sẽ throw khi cố destructuring undefined.
Step 3 — Call u1 Argument: { name: "An", theme: "dark", lang: "vi" }
name="An"role="user"(không có propertyrole, nênundefined→ default)prefs={ theme: "dark", lang: "vi" }
Return: { name: "An", role: "user", preferences: { theme: "dark", lang: "vi" } }
Step 4 — Call u2 Argument: undefined → dùng default {}.
name=undefinedrole="user"prefs={}
Return: { name: "Anonymous", role: "user", preferences: {} }
Step 5 — Call u3 Argument: { name: null, role: null }
name=null→name ?? "Anonymous"→"Anonymous"(nullish coalescing)role=null→ không trigger default vìnull !== undefined
Return: { name: "Anonymous", role: null, preferences: {} }
Key Insight: Default parameter và nullish coalescing (??) xử lý hai vấn đề khác nhau. Default bắt undefined; ?? bắt null và undefined.
7. Prediction Exercise (Bài tập dự đoán)
Đừng chạy code. Đọc và dự đoán output hoặc lỗi, sau đó giải thích tại sao.
Câu 1
function discount(price, rate = 0.1) {
return price * (1 - rate);
}
console.log(discount(100));
console.log(discount(100, 0));
console.log(discount(100, undefined));Câu 2
function sum(first, ...rest) {
return first + rest.length;
}
console.log(sum(10, 20, 30));Câu 3
function config({ host = "localhost", port } = {}) {
return `${host}:${port}`;
}
console.log(config({ port: 3000 }));
console.log(config());Câu 4
function log(level = "INFO", ...msgs) {
return `[${level}] ${msgs.join(" ")}`;
}
console.log(log("WARN", "Disk", "full"));
console.log(log(undefined, "Done"));[Đáp án & Giải thích]
Câu 1: 90, 100, 90
- Giải thích:
discount(100)→ratethiếu, làundefined→ default0.1→90.discount(100, 0)→ratelà0(falsy nhưng không phảiundefined) → không trigger default →100.discount(100, undefined)→ratelàundefined→ default0.1→90.
Câu 2: 12
- Giải thích:
first=10.rest=[20, 30].rest.length=2.10 + 2=12. Rest parameter luôn là array, kể cả chỉ có một phần tử hoặc không có.
Câu 3: "localhost:3000", "localhost:undefined"
- Giải thích:
config({ port: 3000 })→hostkhông có trong object, làundefined→ default"localhost".port=3000. Kết quả"localhost:3000".config()→ argumentundefined→ dùng default{}.host="localhost".portkhông có trong{}, làundefined. Kết quả"localhost:undefined".
Câu 4: "[WARN] Disk full", "[INFO] Done"
- Giải thích:
log("WARN", "Disk", "full")→level="WARN",msgs=["Disk", "full"].log(undefined, "Done")→levellàundefined→ default"INFO".msgs=["Done"].
8. Implementation Lab (Bài lab thực hành)
Level 1 — Guided (Có hướng dẫn)
Viết function buildUrl nhận:
protocol(default"https")domain(bắt buộc)...paths(rest)
Trả về chuỗi URL: protocol://domain/path1/path2
function buildUrl(domain, protocol = "https", ...paths) {
// implement here
// Gợi ý: dùng paths.join("/")
}[Đáp án tham khảo]
function buildUrl(domain, protocol = "https", ...paths) {
return `${protocol}://${domain}/${paths.join("/")}`;
}
console.log(buildUrl("example.com"));
// "https://example.com/"
console.log(buildUrl("example.com", "http", "users", "profile"));
// "http://example.com/users/profile"Giải thích:
protocol= "https" đặt giá trị mặc định cho protocol....pathsdùng rest parameter để gom các path còn lại thành một mảng.paths.join("/")nối các path bằng dấu/.
Level 2 — Partial Scaffold (Khung sẵn)
Hoàn thành function registerUser sử dụng parameter destructuring:
function registerUser({ username, email, age = 18, ...metadata }) {
// Trả về object có dạng:
// { username, email, age, profile: metadata }
// Nếu username hoặc email thiếu, throw Error("Missing required field")
}[Đáp án tham khảo]
function registerUser({ username, email, age = 18, ...metadata }) {
if (!username || !email) {
throw new Error("Missing required field");
}
return {
username,
email,
age,
profile: metadata
};
}
console.log(
registerUser({
username: "an",
email: "an@example.com",
age: 20,
city: "HCM",
role: "student"
})
);
// {
// username: "an",
// email: "an@example.com",
// age: 20,
// profile: {
// city: "HCM",
// role: "student"
// }
// }Giải thích:
{ username, email, age = 18, ...metadata }dùng parameter destructuring.age= 18 sử dụng giá trị mặc định nếu age không được truyền vào....metadatagom các property còn lại vào object metadata.
Nếu thiếu username hoặc email, function sẽ throw Error.
Object trả về dùng shorthand property cho username, email và age.
Level 3 — Independent (Tự viết)
Viết function formatTable nhận một mảng các object hàng (rows) và một mảng tên cột (columns). Dùng destructuring trong parameter để nhận rows và columns, với columns có default là ["name", "value"].
Trả về một chuỗi markdown table.
// Ví dụ:
formatTable([
{ name: "CPU", value: "90%" },
{ name: "RAM", value: "70%" }
]);
// | name | value |
// | --- | --- |
// | CPU | 90% |
// | RAM | 70% |Gợi ý
Dùng columns.map(col => row[col]).join(" | ") để tạo từng dòng. Nhớ xử lý header và separator.
[Đáp án tham khảo]
function formatTable({ rows, columns = ["name", "value"] }) {
const header = `| ${columns.join(" | ")} |`;
const separator = `| ${columns.map(() => "---").join(" | ")} |`;
const body = rows.map(row => {
return `| ${columns.map(col => row[col]).join(" | ")} |`;
});
return [header, separator, ...body].join("\n");
}
console.log(
formatTable({
rows: [
{ name: "CPU", value: "90%" },
{ name: "RAM", value: "70%" }
]
})
);
// | name | value |
// | --- | --- |
// | CPU | 90% |
// | RAM | 70% |Giải thích:
{ rows, columns = ["name", "value"] }dùng destructuring ngay trong parameter.columns.join(" | ")tạo dòng header.columns.map(() => "---")tạo dòng separator.columns.map(col => row[col])lấy giá trị tương ứng của từng cột....bodytrải các dòng dữ liệu vào mảng kết quả.
Cuối cùng join("\n") nối tất cả thành một chuỗi Markdown table.
9. Edge Cases (Các trường hợp ngoại lệ)
Default không bắt null
function greet(name = "Guest") {
return "Hello " + name;
}
greet(null); // "Hello null"Tại sao: null là một giá trị hợp lệ, không phải undefined. Default chỉ trigger bởi undefined.
Cách nhận biết: Function nhận null từ database/API và behavior bất ngờ.
Cách xử lý: Dùng nullish coalescing bên trong body nếu cần bắt cả null:
function greet(name = "Guest") {
return "Hello " + (name ?? "Guest");
}Hoặc validation rõ ràng.
Rest không phải ở cuối
function fn(a, ...rest, b) {}Tại sao: SyntaxError. Rest parameter phải là parameter cuối cùng.
Cách nhận biết: Parser báo lỗi ngay.
Cách xử lý: Rest luôn ở cuối. Nếu cần giữa chừng, dùng array destructuring thay thế.
Destructuring undefined không có default
function fn({ name }) {}
fn(); // TypeError: Cannot destructure property 'name' of 'undefined'Tại sao: JavaScript cố gắng destructuring undefined. Object rỗng {} cũng không có name, nhưng ít nhất không throw ngay lập tức (trả về undefined).
Cách nhận biết: Crash khi function được gọi không có argument.
Cách xử lý: Luôn thêm = {} khi destructuring object trong parameter:
function fn({ name } = {}) {}arguments object không phải array
function oldWay() {
return arguments.map(x => x * 2);
}
oldWay(1, 2, 3); // TypeError: arguments.map is not a functionTại sao: arguments là array-like object, không có array methods.
Cách nhận biết: Lỗi is not a function trên arguments.
Cách xử lý: Dùng rest parameter ...args thay thế. Nếu bắt gặp legacy code dùng arguments, convert bằng Array.from(arguments) hoặc refactor sang rest.
Nhắc nhở: arguments thuộc legacy pattern. Modern code luôn ưu tiên rest parameter.
10. Debug Lab (Bài lab gỡ lỗi)
Symptom (Triệu chứng): Tags của bài viết bị "lây nhiễm" giữa các lần gọi hàm.
function createPost(title, meta = { author: "Admin", tags: [] }) {
meta.tags.push(title);
return { title, author: meta.author, tags: meta.tags };
}
const post1 = createPost("Hello");
const post2 = createPost("World");
console.log(post1.tags); // ["Hello", "World"] ❌
console.log(post2.tags); // ["Hello", "World"] ❌Reproduction (Tái hiện lỗi): Chạy code trên. Quan sát post1.tags chứa cả "World" dù post1 chỉ được tạo với "Hello".
Evidence (Bằng chứng):
post1.tagsban đầu["Hello"].- Sau khi tạo
post2,post1.tagstrở thành["Hello", "World"]. post1.tags === post2.tagstrả vềtrue(cùng reference).
Hypothesis (Giả thuyết): Default parameter meta = { author: "Admin", tags: [] } tạo ra một object duy nhất khi function được định nghĩa. Mỗi lần gọi không truyền meta đều dùng lại object đó. meta.tags.push() mutate cùng một array.
Verification (Xác minh):
function test(meta = { tags: [] }) {
console.log(meta.tags);
meta.tags.push("x");
}
test(); // []
test(); // ["x"]
test(); // ["x", "x"]Xác nhận: cùng một default object được tái sử dụng qua các lần gọi.
Root Cause (Nguyên nhân gốc rễ): Default parameter được evaluate một lần tại thời điểm function creation, không phải mỗi lần call. Object và array là reference type; mutate chúng ảnh hưởng đến các lần gọi sau.
Fix (Sửa):
function createPost(title, meta = {}) {
const author = meta.author ?? "Admin";
const tags = meta.tags ? [...meta.tags] : [];
tags.push(title);
return { title, author, tags };
}Prevention (Phòng ngừa):
- Không dùng object/array mutable trực tiếp làm default parameter.
- Dùng
meta = {}rồi tạo fresh array/object bên trong body. - Nếu cần default phức tạp, dùng factory pattern hoặc tính toán bên trong.
11. Design Exercise (Bài tập thiết kế giải pháp)
Bạn cần viết một hàm sendEmail nhận nhiều cấu hình:
function sendEmail(to, subject, body, from, cc, bcc, attachments) {
// ...
}
sendEmail("a@example.com", "Hello", "Content", "noreply@co.com", null, null, []);function sendEmail({ to, subject, body, from = "noreply@co.com", cc, bcc, attachments = [] }) {
// ...
}
sendEmail({
to: "a@example.com",
subject: "Hello",
body: "Content"
});Câu hỏi:
- Option A có vấn đề gì khi cần bỏ qua
ccvàbcc? - Option B có nhược điểm gì so với Option A?
- Nếu
fromvàattachmentscó default, Option B xử lý như thế nào khi caller không truyền?
[Đáp án tham khảo]
Bạn nghĩ:
- Option A bắt buộc truyền
nullhoặc giá trị placeholder cho các param ở giữa. Khó đọc, dễ nhầm vị trí. - Option B dài hơn khi chỉ có 1-2 param. Caller phải nhớ tên property.
- Option B dùng default parameter trong destructuring:
fromtự động là"noreply@co.com",attachmentslà[]nếu không truyền hoặc truyềnundefined.
- Option A bắt buộc truyền
Kết luận: Với hàm có nhiều optional params, object + destructuring là standard trong modern JavaScript/TypeScript. Nó tự giải quyết vấn đề "positional parameter hell".
12. Production Scenario (Tình huống thực tế)
Context: Một API endpoint nhận query parameters qua object:
function buildQuery({ page = 1, limit = 10, sort = "desc", ...filters }) {
return { page, limit, sort, filters };
}Junior developer sửa code để hỗ trợ null làm giá trị hợp lệ cho limit (nghĩa là "không giới hạn"):
function buildQuery({ page = 1, limit = 10, sort = "desc", ...filters } = {}) {
return { page, limit, sort, filters };
}
buildQuery({ limit: null });Symptom: Kết quả là { page: 1, limit: null, sort: "desc", filters: {} }. Nhưng downstream service nhận limit: null và crash vì mong đợi number.
Constraint: Không được đổi cách gọi API. Phải sửa trong buildQuery.
Câu hỏi:
- Tại sao
limit: nullkhông trigger default10? - Sửa
buildQueryđểnullđược coi như "thiếu" và dùng default10.
[Đáp án tham khảo]
Bạn nghĩ:
- Default parameter chỉ trigger bởi
undefined.nulllà giá trị hợp lệ. - Sửa bằng cách dùng nullish coalescing hoặc validation:jsHoặc dùng default parameter kết hợp với destructuring mặc định:
function buildQuery({ page = 1, limit, sort = "desc", ...filters } = {}) { return { page, limit: limit ?? 10, sort, filters }; }jsfunction buildQuery({ page = 1, limit = 10, sort = "desc", ...filters } = {}) { const finalLimit = limit === null ? 10 : limit; return { page, limit: finalLimit, sort, filters }; }
- Default parameter chỉ trigger bởi
Bài học: API design cần phân biệt rõ "thiếu" (
undefined) và "null" (null). Default parameter chỉ xử lý một nửa vấn đề. Production code thường cần thêm validation layer.
13. AI-assisted Exercise (Bài tập với AI)
Level B — Challenge
- Tự trả lời trước: Viết một đoạn code dùng rest parameter để tính tổng không giới hạn số lượng argument. Không dùng
arguments. - Hỏi AI: "How do I write a JavaScript function that accepts any number of arguments and sums them up?"
- So sánh câu trả lời AI với code của bạn. AI có đề xuất
argumentskhông? Nếu có, đó là legacy pattern. - Verify bằng MDN: tìm "Rest parameters" trên MDN và đọc phần so sánh với
argumentsobject.
Gợi ý
AI thường trả lời đúng về rest parameter nhưng đôi khi vẫn nhắc đến Array.from(arguments) như một alternative. Hãy xem AI có nói rõ arguments là legacy và nên tránh trong modern code không. Nếu không, bạn đã tìm ra điểm mù.
Đáp án tham khảo
Bạn nghĩ:
jsconst sum = (...numbers) => numbers.reduce((a, b) => a + b, 0);AI trả lời (typical):
- You can use the rest parameter:
function sum(...args) { return args.reduce((a, b) => a + b, 0); } - Alternatively, you can use
argumentsobject:Array.from(arguments)... - Rest parameters are cleaner and preferred in modern JavaScript.
- You can use the rest parameter:
So sánh: AI đúng về rest parameter nhưng thường vẫn liệt kê
argumentsnhư một "alternative" hợp lệ thay vì "legacy anti-pattern". Điều này có thể khiến junior nghĩ cả hai đều ổn.Điểm AI nói sai hoặc quá mơ hồ: "Alternatively, you can use
arguments" — câu này thiếu context.argumentskhông chỉ là "less clean"; nó là array-like (không cómap/filter), không hoạt động đúng trong arrow function, và bị deprecated trong nhiều style guide. Trong production modern codebase,argumentsgần như không nên xuất hiện.Kết luận: Nếu bạn chỉ ra được rằng
argumentslà legacy và rest parameter là replacement hoàn toàn, bạn đã hiểu sâu hơn câu trả lời "both are fine" của AI. Concept này sẽ quay lại khi học variadic functions và functional programming ở Stage 8.
14. Teach Back (Dạy lại)
Giả sử một junior developer hỏi bạn:
"Em thấy người ta viết
function fn(a, ...rest)vàfunction fn({ a }). Cái...và cái{ }để làm gì? Có phải cả hai đều là 'destructuring' không?"
Hãy giải thích trong 2 phút, dùng ví dụ cụ thể cho mỗi cái và phân biệt rõ.
Mô phỏng
- Bạn nói: Không, chúng khác nhau.
{ a }trong parameter là destructuring — nghĩa là bạn truyền vào một object, JavaScript mở object đó ra và lấy propertyangay tại chỗ. Còn...restlà rest parameter — nghĩa là bạn truyền vào nhiều argument, JavaScript gom tất cả argument còn lại thành một array tênrest. Ví dụ:function greet({ name })thì bạn gọigreet({ name: "An" }). Cònfunction sum(...nums)thì bạn gọisum(1, 2, 3)vànumslà[1, 2, 3]. Một cái mở hộp, một cái gom hàng.
💡 Tưởng tượng destructuring như nhân viên kho mở thùng hàng ngay tại cửa nhận để lấy từng món. Rest parameter như nhân viên gom mọi thùng còn lại vào một xe đẩy lớn.
Gợi ý đánh giá bản thân
- Đồng nghiệp có hiểu tại sao
...và{ }khác nhau không? - Bạn có nhầm lẫn rest parameter với spread syntax không? (Gợi ý: rest thu gom, spread trải ra.)
- Nếu đồng nghiệp hỏi: "Vậy
...trongconst arr = [1, ...items]là gì?" — bạn trả lời được không? (Đó là spread, sẽ học ở 0.6.8.)
15. Assessment (Đánh giá)
| Objective (Mục tiêu) | Hình thức đánh giá | Task |
|---|---|---|
| Write default parameter (Viết default parameter) | Implementation (Thực hành) | Implementation Lab Level 1 |
| Write rest parameter (Viết rest parameter) | Implementation (Thực hành) | Implementation Lab Level 1 |
| Write parameter destructuring (Viết parameter destructuring) | Implementation (Thực hành) | Implementation Lab Level 2 |
| Predict null vs undefined in defaults (Dự đoán null và undefined) | Prediction (Dự đoán) | Câu 1 & 3, Prediction Exercise |
| Debug mutable default object (Gỡ lỗi default object mutable) | Debug Lab | Debug Lab Section |
| Choose positional vs object params (Chọn positional hay object) | Design Decision | Design Exercise |
16. Exit Criteria (Tiêu chí qua bài)
- [ ] Có thể viết default parameter và dự đoán khi nào nó trigger (chỉ với
undefined). - [ ] Có thể viết rest parameter và biết nó phải ở cuối parameter list.
- [ ] Có thể viết parameter destructuring cho object và array.
- [ ] Có thể kết hợp default + destructuring + rest trong cùng một function.
- [ ] Có thể debug lỗi khi destructuring
undefinedkhông có default object (= {}). - [ ] Có thể debug lỗi mutable object/array được share giữa các calls qua default parameter.
- [ ] Có thể giải thích sự khác biệt giữa rest parameter và
argumentsobject.
17. Spiral Connection (Liên kết xoắn ốc)
Previous (Trước): Arrow Functions (0.5.3) — bạn đã biết cú pháp ngắn gọn để viết function. Giờ bạn học cách định nghĩa "cửa vào" của function linh hoạt hơn.
Current (Hiện tại): Parameters — default để xử lý thiếu, rest để xử lý dư, destructuring để xử lý cấu trúc.
Next (Tiếp theo):
- 0.5.5 — Callback: function được truyền vào hàm khác, thường dùng arrow function với parameter đơn giản.
- 0.5.6 — Higher-order Functions: function trả về function, thường dùng rest để forward arguments.
- 0.6.8 — Spread & Shallow Copy:
...trong spread trải array/object ra, ngược với rest thu gom.- Stage 6 — TypeScript: parameter destructuring là nơi type annotation xuất hiện nhiều nhất trong function signature.
- Stage 8 — React: props chính là object parameter; destructuring props là pattern chuẩn trong mọi component.