Câu hỏi phỏng vấn: một object đã được Object.freeze nhưng profile.name vẫn đổi. Runtime có bỏ qua freeze hay không? Trước khi trả lời, hãy phân biệt object ngoài, object con và reference nối giữa chúng.
Các ví dụ được chạy bằng Node.js 24.18.1; tài liệu MDN được đối chiếu ngày 02/11/2026. Snippet dùng plain object với data property, không xây công cụ deep freeze tổng quát. Không có phép đo hiệu năng hay tuyên bố rằng freeze tự bảo đảm an toàn toàn bộ dữ liệu ứng dụng.
Bắt đầu từ cùng một reference
Lưu thành freeze.cjs, chạy node freeze.cjs:
'use strict';
const assert = require('node:assert/strict');
const profile = { name: 'An' };
const account = { id: 7, profile };
const returned = Object.freeze(account);
assert.equal(returned, account);
assert.equal(account.profile, profile);
assert.equal(Object.isFrozen(account), true);
assert.equal(Object.isFrozen(profile), false);
profile.name = 'Binh';
assert.equal(account.profile.name, 'Binh');
assert.throws(() => { account.id = 8; }, TypeError);
assert.throws(() => { account.profile = { name: 'Chi' }; }, TypeError);
assert.throws(() => { account.active = true; }, TypeError);
assert.equal(account.id, 7);
console.log('shallow freeze cases passed');
Các assertion đã qua. returned không phải bản sao: hàm trả lại object ban đầu. account.profile vẫn trỏ đến chính object profile, và object con ấy chưa bị freeze. Việc sửa profile.name vì thế không thay thế thuộc tính profile trên object ngoài.
Đây là chỗ nên vẽ bằng lời trong phỏng vấn: có hai object, một reference ở bên ngoài, một thuộc tính giữ reference đi vào object con. Nếu chỉ nói “const không immutable” mà không chỉ ra object nào bị thay đổi, bạn mới giải thích được một phần câu hỏi.
Vì sao có lúc lỗi, có lúc chỉ không đổi?
Snippet đặt 'use strict' rõ ràng để những phép gán không hợp lệ bên trên ném TypeError, rồi dùng assert.throws kiểm tra. Không so chuỗi thông báo lỗi vì nội dung có thể khác giữa runtime.
Trong script không strict, một số phép gán vào data property không writable có thể thất bại mà không ném lỗi. Đừng dùng việc “không thấy exception” làm bằng chứng dữ liệu đã thay đổi. Hãy đọc lại giá trị sau thao tác. Module JavaScript tự chạy trong strict mode; khi trao đổi một câu hỏi output, cần chốt ngữ cảnh thực thi.
Strict mode giúp làm rõ một nhóm lỗi lập trình, nhưng nó không tự đi qua các object con để freeze chúng. Bỏ hoặc thêm chỉ thị strict không thay đổi quan hệ reference trong fixture.
Nếu biết rõ cấu trúc, freeze từng phần cần giữ
Chạy snippet độc lập sau bằng cùng Node:
'use strict';
const assert = require('node:assert/strict');
const account = Object.freeze({
id: 7,
profile: Object.freeze({ name: 'An' }),
});
assert.equal(Object.isFrozen(account.profile), true);
assert.throws(() => { account.profile.name = 'Binh'; }, TypeError);
assert.equal(account.profile.name, 'An');
console.log('known nested shape passed');
Lần này object con cũng được freeze và phép gán tên bị chặn trong strict mode. Ví dụ chỉ có một cấu trúc nhỏ đã biết. Nó không phải hàm đệ quy cho dữ liệu bất kỳ, không xử lý vòng tham chiếu, accessor, Map, Set hay class có trạng thái riêng.
Object.isFrozen(account) cũng chỉ trả lời về object được truyền vào, không xác nhận cả đồ thị reference. Khi viết assertion, kiểm tra đúng cấp mà yêu cầu dữ liệu cần giữ. Đừng biến việc object ngoài đã frozen thành điều kiện thay thế cho mọi invariant nghiệp vụ.
Một câu trả lời có thể kiểm chứng
Bạn có thể trình bày theo thứ tự: freeze tác động lên object nào, hàm có tạo copy không, object con có bị tác động không, rồi ngữ cảnh strict quyết định cách quan sát lỗi ghi. Sau đó chạy case cụ thể thay vì dựa vào cách console hiển thị object.
Trong ứng dụng, nếu mục tiêu là tạo phiên bản state mới, freeze không thay cho thao tác dựng dữ liệu mới. Nó có thể giúp phát hiện một số phép ghi ngoài ý muốn trong phạm vi đã freeze, nhưng vẫn cần thiết kế ownership và cập nhật state rõ ràng.
Không thêm một hàm deep freeze ngắn vào mọi payload chỉ để trả lời phỏng vấn. Hãy chốt loại dữ liệu và yêu cầu trước. Với plain object trong bài, hai fixture đủ chứng minh giới hạn nông và cho thấy cách kiểm tra ở đúng cấp reference.


