Skip to content

Lesson 0.5.4 — Parameters ​

Bài 0.5.4 — Parameters
Default, Rest, Destructuring & Arguments • 29 phút
0:00 / 0:00

0. Metadata ​

FieldValue
Stage0 — JavaScript Language Foundation
Module0.5 — Functions
Lesson0.5.4
CompetencyC01.5 — Functions
Depth TargetL2–L3
PrerequisitesArrow Functions (0.5.3), Destructuring (0.6.7), Arrays (0.6.2)
Estimated Cognitive LoadMedium–High

1. Why This Exists (Vì sao cần học) ​

Bạn đã viết được function nhận tham số:

js
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ị:

js
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 undefined là 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 / let và 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ể:

  1. Viết default parameter để xử lý argument bị thiếu hoặc là undefined.
  2. Viết rest parameter để gom các argument còn lại thành một array.
  3. Viết parameter destructuring cho object và array.
  4. Dự đoán giá trị của parameter khi argument là null, 0, "", hoặc undefined.
  5. Phân biệt rest parameter (...args) và arguments object ở 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:

text
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 trong

Mental 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 body

Quan 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 Parameterfunction fn(x = 10) — nếu x nhận undefined, dùng 10.
Rest Parameterfunction fn(...args) — gom mọi argument còn lại thành array args.
Parameter Destructuringfunction fn({ name }) — tách property name từ object argument ngay tại parameter.
Undefined triggerDefault chỉ trigger bởi undefined, không phải null hay 0.

Supporting (Hỗ trợ) ​

ConceptÝ nghĩa
Default với expressionfunction fn(x = getDefault()) — expression được evaluate khi cần.
Rest phải ở cuốifunction fn(a, ...rest, b) là SyntaxError.
Destructuring + defaultfunction fn({ name = "Guest" }) — kết hợp cả hai.
Nested destructuringfunction fn({ user: { name } }) — tách lồng nhau.

Awareness (Biết tồn tại) ​

ConceptLý do chưa đào sâu
arguments objectLegacy way để truy cập tất cả args. Không dùng trong modern code; cơ chế thuộc Stage 1.
arguments vs restarguments 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) ​

  • arguments object 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:

js
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 local
  • role — binding local, default "user" nếu undefined
  • ...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ó property role, nên undefined → 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 = undefined
  • role = "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 ​

js
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 ​

js
function sum(first, ...rest) {
  return first + rest.length;
}
console.log(sum(10, 20, 30));

Câu 3 ​

js
function config({ host = "localhost", port } = {}) {
  return `${host}:${port}`;
}
console.log(config({ port: 3000 }));
console.log(config());

Câu 4 ​

js
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) → rate thiếu, là undefined → default 0.1 → 90.
    • discount(100, 0) → rate là 0 (falsy nhưng không phải undefined) → không trigger default → 100.
    • discount(100, undefined) → rate là undefined → default 0.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 }) → host không có trong object, là undefined → default "localhost". port = 3000. Kết quả "localhost:3000".
    • config() → argument undefined → dùng default {}. host = "localhost". port khô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") → level là 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

js
function buildUrl(domain, protocol = "https", ...paths) {
  // implement here
  // Gợi ý: dùng paths.join("/")
}
[Đáp án tham khảo]
js
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.
  • ...paths dù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:

js
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]
js
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.
  • ...metadata gom 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.

js
// 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]
js
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.
  • ...body trả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

js
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:

js
function greet(name = "Guest") {
  return "Hello " + (name ?? "Guest");
}

Hoặc validation rõ ràng.

Rest không phải ở cuối

js
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

js
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:

js
function fn({ name } = {}) {}

arguments object không phải array

js
function oldWay() {
  return arguments.map(x => x * 2);
}
oldWay(1, 2, 3); // TypeError: arguments.map is not a function

Tạ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.

js
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.tags ban đầu ["Hello"].
  • Sau khi tạo post2, post1.tags trở thành ["Hello", "World"].
  • post1.tags === post2.tags trả 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):

js
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):

js
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:

js
function sendEmail(to, subject, body, from, cc, bcc, attachments) {
  // ...
}

sendEmail("a@example.com", "Hello", "Content", "noreply@co.com", null, null, []);
js
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:

  1. Option A có vấn đề gì khi cần bỏ qua cc và bcc?
  2. Option B có nhược điểm gì so với Option A?
  3. Nếu from và attachments có default, Option B xử lý như thế nào khi caller không truyền?
[Đáp án tham khảo]
  • Bạn nghĩ:

    1. Option A bắt buộc truyền null hoặc giá trị placeholder cho các param ở giữa. Khó đọc, dễ nhầm vị trí.
    2. Option B dài hơn khi chỉ có 1-2 param. Caller phải nhớ tên property.
    3. Option B dùng default parameter trong destructuring: from tự động là "noreply@co.com", attachments là [] nếu không truyền hoặc truyền undefined.
  • 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:

js
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"):

js
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:

  1. Tại sao limit: null không trigger default 10?
  2. Sửa buildQuery để null được coi như "thiếu" và dùng default 10.
[Đáp án tham khảo]
  • Bạn nghĩ:

    1. Default parameter chỉ trigger bởi undefined. null là giá trị hợp lệ.
    2. Sửa bằng cách dùng nullish coalescing hoặc validation:
      js
      function buildQuery({ page = 1, limit, sort = "desc", ...filters } = {}) {
        return {
          page,
          limit: limit ?? 10,
          sort,
          filters
        };
      }
      Hoặc dùng default parameter kết hợp với destructuring mặc định:
      js
      function buildQuery({ page = 1, limit = 10, sort = "desc", ...filters } = {}) {
        const finalLimit = limit === null ? 10 : limit;
        return { page, limit: finalLimit, sort, filters };
      }
  • 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

  1. 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.
  2. Hỏi AI: "How do I write a JavaScript function that accepts any number of arguments and sums them up?"
  3. So sánh câu trả lời AI với code của bạn. AI có đề xuất arguments không? Nếu có, đó là legacy pattern.
  4. Verify bằng MDN: tìm "Rest parameters" trên MDN và đọc phần so sánh với arguments object.

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ĩ:

    js
    const 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 arguments object: Array.from(arguments)...
    • Rest parameters are cleaner and preferred in modern JavaScript.
  • So sánh: AI đúng về rest parameter nhưng thường vẫn liệt kê arguments như 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. arguments khô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, arguments gần như không nên xuất hiện.

  • Kết luận: Nếu bạn chỉ ra được rằng arguments là 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 property a ngay tại chỗ. Còn ...rest là 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ên rest. Ví dụ: function greet({ name }) thì bạn gọi greet({ name: "An" }). Còn function sum(...nums) thì bạn gọi sum(1, 2, 3) và nums là [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 ... trong const 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 LabDebug Lab Section
Choose positional vs object params (Chọn positional hay object)Design DecisionDesign 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 undefined khô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à arguments object.

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.
📴 Offline Mode — Content served from cache