Skip to content

Lesson 0.6.7 — Destructuring ​

Bài 0.6.7 — Destructuring
Object, Array, Default values & Nested destructuring • 25 phút
0:00 / 0:00

0. Metadata ​

FieldValue
Stage0 — JavaScript Language Foundation
Module0.6 — Data Structures
Lesson0.6.7
CompetencyC01.6 — Arrays / Objects
Depth TargetL2–L3
PrerequisitesObjects (0.6.5), Object Utilities (0.6.6), Arrays (0.6.2), Array Iteration (0.6.3)
Estimated Cognitive LoadMedium

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

Bạn đã biết truy cập object bằng obj.name và obj["name"]. Nhưng khi cần lấy nhiều property cùng lúc, code trở nên lặp lại và nói về cơ chế thay vì intent.

Xét đoạn code:

js
function displayUser(user) {
  const name = user.name;
  const email = user.email;
  const role = user.role || "guest";
  const theme = user.settings ? user.settings.theme : "light";

  return `${name} (${email}) — ${role}, theme: ${theme}`;
}

Vấn đề cốt lõi

const name = user.name nói: "Tôi đang lấy property name từ user." Nhưng intent thực sự chỉ là: "Tôi cần name, email, role từ user." Destructuring cho phép bạn viết intent đó trực tiếp.

Ngoài ra, destructuring còn cung cấp:

  • Default value: role = "guest" khi property missing hoặc undefined.
  • Rename: name: displayName để tránh xung đột tên biến.
  • Nested access: settings.theme trong một bước.
  • Array unpacking: lấy phần tử theo vị trí thay vì index.

Bài này dạy bạn dùng destructuring như một khai báo intent: tôi cần những gì từ structure này.

2. Prerequisites (Yêu cầu đầu vào) ​

Trước khi học bài này, bạn cần:

  • Truy cập object bằng dot và bracket notation (0.6.5).
  • Biết Object.entries trả về [key, value] pairs (0.6.6).
  • Biết array index và length (0.6.2).
  • Hiểu const/let và assignment (0.2.2).

WARNING

Nếu bạn chưa chắc tại sao obj.missing trả về undefined nhưng const { a } = null lại throw, quay lại 0.6.5. Sự khác biệt giữa "property không tồn tại" và "object không tồn tại" là trung tâm của edge cases trong bài này.

3. Learning Objectives (Mục tiêu học tập) ​

Sau bài này, bạn có thể:

  1. Sử dụng object destructuring để trích xuất nhiều property trong một câu lệnh.
  2. Sử dụng array destructuring để trích xuất phần tử theo vị trí.
  3. Áp dụng default values khi property là undefined.
  4. Đổi tên property trong destructuring để tránh xung đột.
  5. Truy cập nested property qua nested destructuring.
  6. Sử dụng rest pattern (...rest) trong destructuring để lấy phần còn lại.
  7. Nhận diện khi destructuring sẽ throw (source là null/undefined).

4. Mental Model (Mô hình tư duy) ​

Mental Model

Destructuring = Mở hộp và lấy đồ theo tên/vị trí

Object Destructuring (Mở hộp có nhãn)
  { name, email } = user
       ↓
  Từ hộp `user`, lấy món đồ tên `name` → biến `name`
  Từ hộp `user`, lấy món đồ tên `email` → biến `email`

  { name: displayName } = user
       ↓
  Lấy món `name`, đặt vào biến `displayName`

  { role = "guest" } = user
       ↓
  Lấy món `role`. Nếu hộp không có hoặc là undefined → dùng "guest"

Array Destructuring (Mở hộp theo thứ tự)
  [first, second] = items
       ↓
  Lấy phần tử 0 → biến `first`
  Lấy phần tử 1 → biến `second`

  [first, , third] = items
       ↓
  Lấy 0, bỏ qua 1, lấy 2

  [head, ...tail] = items
       ↓
  Lấy 0, phần còn lại thành mảng `tail`

Quy tắc vàng:

  • Destructuring là pattern matching trên shape của value.
  • Object destructuring dựa trên tên key, không quan tâm thứ tự.
  • Array destructuring dựa trên vị trí index.
  • Default value chỉ kích hoạt khi property là undefined, không phải null, 0, "", false.
  • Rest (...) phải ở cuối pattern.

5. Core Concepts (Các khái niệm cốt lõi) ​

Essential (Bắt buộc) ​

ConceptÝ nghĩa
Object Destructuringconst { a, b } = obj — tạo biến a và b từ property cùng tên.
Array Destructuringconst [x, y] = arr — tạo biến x (index 0), y (index 1).
Default Valueconst { a = 1 } = obj — nếu obj.a là undefined, a = 1.
Renameconst { a: b } = obj — lấy property a, đặt vào biến b.
Nested Destructuringconst { a: { b } } = obj — truy cập obj.a.b trong một pattern.
Rest in Destructuringconst { a, ...rest } = obj hoặc const [x, ...rest] = arr. rest chứa phần còn lại.

Supporting (Hỗ trợ) ​

ConceptÝ nghĩa
Destructuring in Parametersfunction fn({ name }) — destructuring ngay trong parameter list.
Swap Variables[a, b] = [b, a] — hoán đổi không cần biến tạm.

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

ConceptLý do chưa đào sâu
Computed key destructuringconst { [expr]: name } = obj. Dùng bracket trong pattern. Học khi cần dynamic key.
Iterator destructuringconst [a, b] = new Set([1, 2]). Dựa trên iterator protocol. Thuộc Stage 2.

Out of Scope (Không thuộc bài này) ​

  • Destructuring với complex nested beyond 2 levels (cognitive load).
  • for...of destructuring (Stage 2 — Iteration protocol).
  • TypeScript tuple destructuring (Stage 6).
  • React props destructuring pattern (Stage 8 — preview có thể nhưng không đào sâu).

6. Worked Example (Ví dụ phân tích từng bước) ​

Bài toán: Viết function nhận API response và trích xuất thông tin hiển thị.

js
const response = {
  status: 200,
  data: {
    user: {
      id: 42,
      name: "Alice",
      email: "alice@example.com",
      profile: {
        role: "admin",
        theme: "dark"
      }
    }
  }
};

Yêu cầu:

  1. Lấy name, email.
  2. Lấy role từ nested profile, đổi tên thành userRole.
  3. Nếu theme missing, default là "light".
  4. Lấy tất cả property còn lại của profile vào otherProfile.
js
function extractInfo(response) {
  const user = response.data.user;
  const name = user.name;
  const email = user.email;
  const userRole = user.profile.role;
  const theme = user.profile.theme ? user.profile.theme : "light";

  return { name, email, userRole, theme };
}
js
function extractInfo({ data: { user } }) {
  const {
    name,
    email,
    profile: {
      role: userRole,
      theme = "light",
      ...otherProfile
    }
  } = user;

  return { name, email, userRole, theme, otherProfile };
}

Walkthrough

Step 1 — Parameter Destructuring{ data: { user } } unpack ngay trong parameter. response → data → user. Không cần const user = response.data.user.

Step 2 — Object Destructuring name, emailconst { name, email } = user tạo biến name và email từ property cùng tên. Nếu property missing → undefined.

Step 3 — Nested Destructuring + Renameprofile: { role: userRole } đi vào user.profile, lấy role, đặt vào biến userRole. Rename giúp tránh xung đột với từ khóa hoặc tên rõ hơn.

Step 4 — Default Valuetheme = "light" — nếu user.profile.theme là undefined, biến theme nhận "light". Nếu là null, theme vẫn là null (default không kích hoạt).

Step 5 — Rest...otherProfile lấy tất cả property còn lại của profile (ngoài role và theme) thành object mới.

Key Insight: Destructuring không chỉ ngắn gọn hơn — nó khai báo shape của data mà function cần. Đọc parameter là biết function mong đợi gì từ input.

7. Prediction Exercise (Bài tập dự đoán) ​

Đừng chạy code. Đọc và dự đoán output, sau đó giải thích tại sao.

Câu 1 ​

js
const user = { name: "Alice", age: 24 };
const { name: fullName, role = "user" } = user;
console.log(fullName, role);

Câu 2 ​

js
const coords = [10, 20, 30, 40];
const [x, , ...rest] = coords;
console.log(x, rest);

Câu 3 ​

js
const user = { profile: { name: "Bob" } };
const { profile: { name, age = 18 } } = user;
console.log(name, age);

Câu 4 ​

js
const data = null;
const { value } = data;
console.log(value);

Câu 5 ​

js
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b);
[Đáp án & Giải thích]

Câu 1: "Alice" "user" — Rename + Default

  • Giải thích: name: fullName lấy property name, đặt vào biến fullName. role không tồn tại trong user → undefined → default "user" kích hoạt.

Câu 2: 10 [30, 40] — Skip + Rest

  • Giải thích: [x, , ...rest] lấy index 0 (10), bỏ qua index 1 (20), rest lấy từ index 2 đến hết ([30, 40]).

Câu 3: "Bob" 18 — Nested + Default

  • Giải thích: Đi vào user.profile, lấy name = "Bob". age không tồn tại trong profile → undefined → default 18.

Câu 4: TypeError: Cannot destructure property 'value' of 'null' — Source là null

  • Giải thích: Destructuring yêu cầu source phải là object (hoặc array). null không phải object → throw. Khác với data.value (trả về undefined).

Câu 5: 2 1 — Swap

  • Giải thích: [a, b] = [b, a] unpack mảng [2, 1] vào a và b. Hoán đổi không cần biến tạm.

8. Implementation Lab (Bài lab thực hành) ​

Level 1 — Guided (Có hướng dẫn) ​

Viết function formatUser dùng destructuring trong parameter để lấy name, email, và role với default "guest".

js
function formatUser(___________) {
  return `${name} <${email}> (${role})`;
}

const user = { name: "Alice", email: "a@b.com" };
console.log(formatUser(user));
// "Alice <a@b.com> (guest)"

Gợi ý

Destructuring object ngay trong parameter: function formatUser({ name, email, role = "guest" }).

[Đáp án tham khảo]
js
function formatUser({ name, email, role = "guest" }) {
  return `${name} <${email}> (${role})`;
}

const user = { name: "Alice", email: "a@b.com" };
console.log(formatUser(user));
// "Alice <a@b.com> (guest)"

console.log(formatUser({ name: "Bob", email: "b@c.com", role: "admin" }));
// "Bob <b@c.com> (admin)"

Giải thích:

  • Destructuring trong parameter khai báo ngay: function cần object có name, email, và tùy chọn role.
  • role = "guest" cung cấp default khi missing hoặc undefined.
  • Không cần const name = user.name trong body.

Level 2 — Partial Scaffold (Khung sẵn) ​

Hoàn thành destructuring để trích xuất thông tin từ nested API response.

js
function extractUser(response) {
  const {
    _______: _______,
    data: {
      user: {
        _______,
        profile: {
          _______: avatar,
          _______ = "light"
        }
      }
    }
  } = response;

  return { status, name, avatar, theme };
}

const api = {
  status: 200,
  data: {
    user: {
      name: "Alice",
      profile: { avatar: "a.jpg", theme: "dark" }
    }
  }
};

console.log(extractUser(api));
// { status: 200, name: "Alice", avatar: "a.jpg", theme: "dark" }
[Đáp án tham khảo]
js
function extractUser(response) {
  const {
    status,
    data: {
      user: {
        name,
        profile: {
          avatar,
          theme = "light"
        }
      }
    }
  } = response;

  return { status, name, avatar, theme };
}

const api = {
  status: 200,
  data: {
    user: {
      name: "Alice",
      profile: { avatar: "a.jpg", theme: "dark" }
    }
  }
};

console.log(extractUser(api));
// { status: 200, name: "Alice", avatar: "a.jpg", theme: "dark" }

Giải thích:

  • status lấy trực tiếp từ response.
  • data: { user: { name, profile: ... } } đi sâu nested.
  • avatar là shorthand destructuring khi tên biến trùng tên property. Nếu cần đổi tên (ví dụ avatar: userAvatar) mới dùng dạng dài.
  • theme = "light" có default.

Level 3 — Independent (Tự viết) ​

Viết các function sau sử dụng destructuring:

js
// 1. getFirstAndLast(items) → Trả về { first, last } dùng array destructuring
//    Ví dụ: getFirstAndLast(["a", "b", "c"]) → { first: "a", last: "c" }

// 2. extractConfig(settings) → Lấy host, port (default 3000), rename timeout → maxTimeout
//    Ví dụ: extractConfig({ host: "localhost", timeout: 5000 })
//    → { host: "localhost", port: 3000, maxTimeout: 5000 }

// 3. parseCoords(point) → point là { coords: [x, y] }. Dùng nested destructuring
//    Ví dụ: parseCoords({ coords: [10, 20] }) → { x: 10, y: 20 }

// Sử dụng:
console.log(getFirstAndLast(["red", "green", "blue"]));
// { first: "red", last: "blue" }

console.log(extractConfig({ host: "api.example.com" }));
// { host: "api.example.com", port: 3000, maxTimeout: undefined }

console.log(parseCoords({ coords: [5, 10] }));
// { x: 5, y: 10 }
[Đáp án tham khảo]
js
// middleAndLast sẽ là rest
function getFirstAndLast(items) {
  const [first, ...middleAndLast] = items;
  const last = middleAndLast[middleAndLast.length - 1] || first;
  return { first, last };
}

Hoặc đơn giản hơn:

js
function getFirstAndLast(items) {
  const [first] = items;
  const [last] = items.slice(-1);
  return { first, last };
}

js
function extractConfig(settings) {
  const { host, port = 3000, timeout: maxTimeout } = settings;
  return { host, port, maxTimeout };
}

function parseCoords(point) {
  const { coords: [x, y] } = point;
  return { x, y };
}

console.log(getFirstAndLast(["red", "green", "blue"]));
// { first: "red", last: "blue" }

console.log(extractConfig({ host: "api.example.com" }));
// { host: "api.example.com", port: 3000, maxTimeout: undefined }

console.log(parseCoords({ coords: [5, 10] }));
// { x: 5, y: 10 }

Giải thích:

  • getFirstAndLast: [first, ...rest] lấy phần tử đầu và phần còn lại. rest[rest.length - 1] lấy cuối. Nếu mảng 1 phần tử, rest rỗng, dùng || first.
  • const [first] = items lấy phần tử đầu bằng array destructuring.
  • items.slice(-1) trả về mảng chứa phần tử cuối. const [last] destructuring mảng đó để lấy giá trị.
  • Cả hai đều dùng array destructuring, không mutate items.
  • extractConfig: port = 3000 default. timeout: maxTimeout rename.
  • parseCoords: { coords: [x, y] } nested array destructuring trong object.

9. Edge Cases (Các trường hợp ngoại lệ) ​

Destructuring null hoặc undefined throw

js
const data = null;
const { name } = data; // TypeError

Tại sao: Destructuring cần source là object (hoặc array). null/undefined không thể convert.

Cách nhận biết: TypeError khi API trả về null thay vì object.

Cách xử lý: Guard clause hoặc default object:

js
const { name } = data || {};

Default value chỉ kích hoạt với undefined

js
const { role = "guest" } = { role: null };
console.log(role); // null

Tại sao: Default chỉ áp dụng khi property là undefined. null là giá trị explicit, không trigger default.

Cách nhận biết: Biến nhận null thay vì default value.

Cách xử lý: Nếu cần xử lý cả null, dùng nullish coalescing sau destructuring (Stage 0.4.3/Stage 1), hoặc validate trước.

Missing intermediate nested property throw

js
const user = {};
const { profile: { name } } = user;
// TypeError: Cannot destructure property 'name' of 'undefined'

Tại sao: user.profile là undefined. Đi sâu vào undefined.name throw.

Cách nhận biết: TypeError khi destructuring nested object mà level trung gian missing.

Cách xử lý: Cung cấp default cho intermediate:

js
const { profile: { name } = {} } = user;

Hoặc guard clause.

Rest phải ở cuối

js
const [a, ...rest, b] = [1, 2, 3]; // SyntaxError

Tại sao: Rest element phải là element cuối cùng trong pattern.

Cách nhận biết: SyntaxError ngay khi parse.

Cách xử lý: Đặt ...rest cuối cùng.

Destructuring không có declaration cần parentheses cho object

js
{ a } = { a: 1 }; // SyntaxError
({ a } = { a: 1 }); // ✅

Tại sao: Parser hiểu { a } ở đầu câu là block statement, không phải object literal. Cần bọc trong () để force expression context.

Cách nhận biết: SyntaxError unexpected token =.

Cách xử lý: Thêm parentheses: ({ a } = obj).

10. Debug Lab (Bài lab gỡ lỗi) ​

Symptom (Triệu chứng): App crash khi API trả về user chưa có profile.

js
function getTheme(user) {
  const { profile: { settings: { theme } } } = user;
  return theme;
}

const userA = {
  profile: { settings: { theme: "dark" } }
};
console.log(getTheme(userA)); // "dark" ✅

const userB = { profile: {} };
console.log(getTheme(userB));
// TypeError: Cannot destructure property 'theme' of 'undefined'

Reproduction (Tái hiện lỗi): Chạy code với userB.

Evidence (Bằng chứng):

  • userB.profile tồn tại nhưng userB.profile.settings là undefined.
  • Destructuring cố gắng truy cập undefined.theme.

Hypothesis (Giả thuyết): Nested destructuring profile: { settings: { theme } } giả định profile.settings tồn tại. Khi settings là undefined, JavaScript không thể destructuring tiếp.

Verification (Xác minh):

js
console.log(userB.profile.settings); // undefined

Root Cause (Nguyên nhân gốc rễ): Destructuring nested không tự động "bail out" khi intermediate level missing. Nó cố gắng access property trên undefined.

Fix (Sửa):

js
function getTheme(user) {
  const { profile: { settings: { theme } = {} } = {} } = user;
  return theme;
}

Hoặc an toàn hơn:

js
function getTheme(user) {
  if (!user?.profile?.settings) return "light";
  return user.profile.settings.theme;
}

Prevention (Phòng ngừa):

  • Khi destructuring nested từ API response, luôn hỏi: "Level trung gian có thể missing không?"
  • Cung cấp default object cho mỗi level: { level1: { level2: { x } = {} } = {} }.
  • Hoặc dùng optional chaining (ES2020) khi environment cho phép — nhưng ở Stage 0, guard clause hoặc default object là cách hiểu rõ mechanism.

11. Design Exercise (Bài tập thiết kế giải pháp) ​

Bạn cần viết function nhận config object.

js
function setup({ host, port, db, cache, logger, retry, timeout }) {
  connectDB(db);
  initCache(cache);
  setupLogger(logger);
  // ... 20 lines later
  if (timeout > 0) setTimeout(retry, timeout);
}
js
function setup(config) {
  const { host, port } = config;
  initServer(host, port);

  const { db } = config;
  connectDB(db);

  const { timeout, retry } = config;
  if (timeout > 0) setTimeout(retry, timeout);
}

Câu hỏi:

  1. Option A có lợi gì về readability?
  2. Option B có lợi gì khi một số property có thể missing?
  3. Nếu config có 15 properties nhưng function chỉ dùng 4, Option A có vấn đề gì?
[Đáp án tham khảo]
  • Bạn nghĩ:

    1. Option A: Nhìn vào đầu function là biết toàn bộ dependencies. Self-documenting. Dễ so sánh với function signature.
    2. Option B: Nếu db missing, lỗi chỉ xảy ra khi đến dòng connectDB. Dễ bọc try/catch cục bộ. Không throw ngay khi vào function nếu property unused missing (thực ra destructuring missing property chỉ là undefined, không throw — nhưng nếu nested thì throw).
    3. Option A với 15 properties dài và nói "function cần nhiều thứ" có thể là smell — function làm quá nhiều. Nên nhóm config lại hoặc tách function.
  • Kết luận: Destructure ở top cho function nhỏ, clear. Destructure khi cần cho function lớn, defensive, hoặc khi property có thể nested missing.

12. Production Scenario (Tình huống thực tế) ​

Context: API user profile:

js
const user = {
  id: 1,
  name: "Alice",
  preferences: {
    notifications: { email: true, sms: false }
  }
};

Code hiện tại:

js
function shouldNotify(user, channel) {
  const { preferences: { notifications } } = user;
  return notifications[channel];
}

Symptom: Khi user mới đăng ký chưa cài đặt preferences, user.preferences là undefined. App crash: Cannot destructure property 'notifications' of 'undefined'. Hoặc khi backend thêm field preferences: null.

Constraint: Không thể thay đổi API. Phải handle cả preferences missing, notifications missing, và channel missing.

Câu hỏi:

  1. Tại sao code crash với user mới?
  2. Viết lại dùng destructuring an toàn với default ở mỗi level.
  3. Nếu channel không tồn tại trong notifications, function nên trả về gì?
[Đáp án tham khảo]
  • Bạn nghĩ:

    1. user.preferences là undefined với user mới. Destructuring preferences: { notifications } cố access undefined.notifications.
    2. js
      function shouldNotify(user, channel) {
        const { preferences: { notifications } = {} } = user || {};
        if (!notifications) return false;
        return notifications[channel] || false;
      }
    3. Nên trả về false (default opt-out) hoặc giá trị default tùy business logic. Không nên throw.
  • Nâng cao (Awareness — Stage 2): Nếu đã học computed property destructuring và nullish coalescing:

    js
    function shouldNotify(user, channel) {
      const {
        preferences: {
          notifications: { [channel]: enabled } = {}
        } = {}
      } = user;
    
      return enabled ?? false;
    }
  • Bài học: Destructuring nested từ external data (API) luôn cần defensive defaults. Đừng giả định shape cố định.

13. AI-assisted Exercise (Bài tập với AI) ​

Level B — Challenge

  1. Tự trả lời trước: Viết đoạn code destructuring với default value. Dự đoán output khi property là null.
    js
    const user = { role: null };
    const { role = "guest" } = user;
    console.log(role);
  2. Hỏi AI: "Tại sao role là null thay vì "guest"? Tôi đã đặt default value mà?"
  3. So sánh câu trả lời AI với nhận định của bạn. AI có nhấn mạnh rằng default trong destructuring chỉ kích hoạt với undefined, không phải null?
  4. Verify bằng MDN: tìm "Destructuring assignment" trên MDN, đọc phần "Default values".

Gợi ý

AI thường biết câu trả lời đúng nhưng đôi khi giải thích mơ hồ bằng cách nói "null is a value, undefined means missing". Nếu AI không chỉ ra rằng đây là quy tắc cốt lõi của destructuring spec — default chỉ trigger khi property evaluate to undefined — bạn đã tìm ra điểm mù. AI cũng có thể nhầm lẫn với function parameter default (cũng chỉ undefined).

Đáp án tham khảo
  • Bạn nghĩ: role là null vì default value trong destructuring chỉ kích hoạt khi property là undefined. null là giá trị explicit, không phải "missing". Quy tắc này giống function parameter default.

  • AI trả lời (typical):

    • Default values in destructuring only apply when the property is undefined.
    • null is an assigned value, so the default does not apply.
    • The result is null.
  • So sánh: AI thường đúng về behavior nhưng đôi khi không giải thích tại sao điều này quan trọng trong production: nếu API trả về { role: null } (explicit "no role") thì default không nên kích hoạt — đó là intent đúng. Nhưng nếu developer nghĩ default sẽ cover cả null, họ sẽ có bug.

  • Điểm AI nói sai hoặc quá mơ hồ: "null is a value" — đúng nhưng chưa đủ. AI hiếm khi nói rõ: "Nếu bạn cần xử lý cả null và undefined, bạn phải dùng logic sau destructuring: const finalRole = role ?? 'guest' (nullish coalescing). Destructuring default không thay thế được."

  • Kết luận: Nếu bạn chỉ ra được rằng destructuring default và nullish coalescing (??) là hai cơ chế khác nhau cho hai use case khác nhau, bạn đã hiểu sâu hơn AI. Concept này sẽ quay lại ở Stage 1 (Function default parameters), Stage 6 (TypeScript optional properties), và Stage 8 (React default props pattern).

14. Teach Back (Dạy lại) ​

Giả sử một junior developer hỏi bạn:

"Anh/chị ơi, const name = user.name với const { name } = user có gì khác nhau đâu? Em thấy cái thứ hai chỉ là viết tắt thôi mà? Tại sao người ta bảo dùng destructuring 'tốt hơn'?"

Hãy giải thích trong 2 phút, dùng đúng terminology: intent, shape declaration, default value, nested access.

Mô phỏng
  • Bạn nói: Về cơ bản, destructuring là syntax để lấy property. Nhưng nó làm được nhiều hơn "viết tắt".

Thứ nhất — Intent: Khi bạn viết const { name, email } = user, bạn đang khai báo: "Function này cần name và email từ user." Đọc code là thấy shape. Còn const name = user.name nói về cơ chế: "Tôi đang truy cập property name."

Thứ hai — Default: const { role = "guest" } = user xử lý missing property trong một bước. Với dot notation bạn phải viết const role = user.role !== undefined ? user.role : "guest".

Thứ ba — Nested: const { profile: { name } } = user lấy user.profile.name mà không cần tạo biến trung gian const profile = user.profile.

Thứ tư — Function parameter: function greet({ name }) nói rõ function mong đợi object có name ngay từ signature.

💡 Tưởng tượng dot notation như mở từng ngăn kéo bằng tay. Destructuring như đưa cho bạn một checklist: "Tôi cần cái này, cái này, và cái này" — rồi tự động lấy ra.

Gợi ý đánh giá bản thân

  • Đồng nghiệp có hiểu tại sao destructuring là "khai báo intent" không?
  • Bạn có tránh được việc nói "nó chỉ là syntax sugar" không? (Nó là syntax sugar nhưng có semantics riêng về default và nested.)
  • Nếu đồng nghiệp hỏi: "Vậy khi nào em không dùng destructuring?" — bạn trả lời được không? (Gợi ý: khi property name động, hoặc khi cần guard phức tạp trước khi access nested.)
  • Nếu đồng nghiệp viết { a } = obj và bị SyntaxError — bạn giải thích được tại sao và sửa trong 5 giây không? (Gợi ý: cần parentheses ({ a } = obj).)

15. Assessment (Đánh giá) ​

Objective (Mục tiêu)Hình thức đánh giáTask
Object destructuring (Destructuring object)Implementation (Thực hành)Implementation Lab Level 1
Array destructuring (Destructuring array)Implementation (Thực hành)Implementation Lab Level 3
Default values (Giá trị mặc định)Prediction (Dự đoán)Prediction Câu 1, 3
Rename property (Đổi tên property)Implementation (Thực hành)Implementation Lab Level 3
Nested destructuring (Destructuring lồng nhau)Implementation (Thực hành)Implementation Lab Level 2–3
Handle null/undefined source (Xử lý null/undefined)Debug LabDebug Lab Section
Distinguish undefined vs null for defaults (Phân biệt undefined/null)AI-assistedAI-assisted Section
Explain intent vs mechanismTeach BackTeach Back Section

16. Exit Criteria (Tiêu chí qua bài) ​

  • [ ] Có thể sử dụng object destructuring để trích xuất nhiều property trong một câu lệnh.
  • [ ] Có thể sử dụng array destructuring để trích xuất phần tử theo vị trí, bao gồm skip và rest.
  • [ ] Có thể áp dụng default values trong destructuring và biết chỉ kích hoạt với undefined.
  • [ ] Có thể đổi tên property trong destructuring (oldName: newName).
  • [ ] Có thể viết nested destructuring đến 2 cấp.
  • [ ] Có thể nhận diện khi destructuring sẽ throw (source là null/undefined).
  • [ ] Có thể debug lỗi nested destructuring khi intermediate level missing.
  • [ ] Có thể sử dụng destructuring trong function parameters để khai báo expected shape.

17. Spiral Connection (Liên kết xoắn ốc) ​

Previous (Trước): Object Utilities (0.6.6) — bạn đã biết chuyển object ↔ array bằng Object.entries. Giờ bạn học cách "mở" object/array để lấy dữ liệu một cách declarative.

Current (Hiện tại): Destructuring — object/array unpacking, default values, rename, nested, rest. Khai báo intent qua shape.

Next (Tiếp theo):

  • 0.6.8 (Spread & Shallow Copy) — Spread ... là "chiều ngược lại" của destructuring: gom lại thay vì mở ra. { ...obj } tạo shallow copy. Kết hợp destructuring + spread để update object immutably.
  • Stage 1 (Execution Model) — Parameter binding: tại sao function({ name }) hoạt động? Destructuring là syntax sugar cho một loạt GetValue operations trong execution context.
  • Stage 6 (TypeScript) — Tuple destructuring: const [a, b]: [string, number] = arr. Object destructuring với type annotations.
  • Stage 8 (React) — Props destructuring là pattern bắt buộc: function Button({ label, onClick }). Default props qua destructuring default. Spread props: <Button {...props} />.
📴 Offline Mode — Content served from cache