Bạn muốn tạo ba item mặc định bằng Array(3).map(...), nhưng callback không chạy. Trong phỏng vấn, câu trả lời hữu ích cần giải thích vị trí trống trong array và chỉ ra cách kiểm tra, thay vì chỉ đổi sang cú pháp khác.
Các snippet trong bài đã chạy bằng Node.js 24.18.1, đối chiếu MDN ngày 31/10/2026. Chúng kiểm tra hành vi array đồng bộ, không có UI, network hoặc số liệu benchmark.
1. Length không chứng minh đã có phần tử
Array(3) tạo một array có length bằng 3 nhưng chưa có thuộc tính tại các index 0, 1, 2. Các vị trí đó thường được gọi là empty slot hoặc hole. map bỏ qua vị trí trống, nên callback không được gọi như khi array có ba giá trị đã gán.
import assert from 'node:assert/strict';
const holes = Array(3);
let calls = 0;
const mapped = holes.map(() => {
calls += 1;
return 'item';
});
assert.equal(holes.length, 3);
assert.equal(calls, 0);
assert.equal(mapped.length, 3);
assert.equal(Object.hasOwn(mapped, 0), false);
console.log(calls, Object.keys(mapped));
Kết quả là 0 lần gọi và danh sách key rỗng. Không dùng riêng cách console trình bày array để kết luận, vì mỗi môi trường có thể hiển thị vị trí trống khác nhau. Assertions về callback và thuộc tính làm phép thử rõ hơn.
2. Undefined là một giá trị đã gán
Hai array có thể đều trả undefined khi đọc index 0 nhưng có cấu trúc khác nhau. Một bên không có thuộc tính đó, bên còn lại có thuộc tính với giá trị undefined. Đây là lý do chỉ đọc array[0] chưa đủ phân biệt.
import assert from 'node:assert/strict';
const holes = Array(3);
const values = [undefined, undefined, undefined];
assert.equal(holes[0], values[0]);
assert.equal(Object.hasOwn(holes, 0), false);
assert.equal(Object.hasOwn(values, 0), true);
assert.deepEqual(values.map((_, index) => index), [0, 1, 2]);
console.log(Object.keys(values));
Ví dụ dùng Object.hasOwn để hỏi thuộc tính riêng của array. Không cố tình gán thuộc tính số vào Array.prototype trong ứng dụng; các ví dụ đang giả định prototype chuẩn, không bị chỉnh sửa thêm các index.
3. Tạo phần tử bằng factory của Array.from
Khi mục tiêu là tạo N giá trị, Array.from với object có length và callback diễn đạt trực tiếp yêu cầu đó. Callback có index và tạo giá trị tại mỗi vị trí trong array kết quả.
import assert from 'node:assert/strict';
const rows = Array.from({length: 3}, (_, index) => ({
id: index + 1,
selected: false,
}));
rows[0].selected = true;
assert.deepEqual(rows.map(row => row.id), [1, 2, 3]);
assert.equal(rows[1].selected, false);
assert.notEqual(rows[0], rows[1]);
console.log(rows);
Object literal nằm bên trong callback nên mỗi lần gọi tạo một object mới. Việc kiểm tra tham chiếu khác nhau là cần thiết khi bạn muốn các item có state độc lập, không chỉ kiểm tra nội dung ban đầu nhìn giống nhau.
ID theo index ở đây chỉ phục vụ fixture tĩnh. Với dữ liệu có thể thêm, xóa và sắp xếp trong sản phẩm, cần ID thật của item; không lấy snippet khởi tạo này làm quy tắc định danh cho mọi danh sách UI.
4. Vì sao fill({}) tạo vấn đề khác?
fill có thể điền các vị trí trống, nhưng đối số object được dùng lại cho mọi vị trí. Nó không gọi constructor hoặc clone object cho từng phần tử.
import assert from 'node:assert/strict';
const shared = Array(3).fill({selected: false});
shared[0].selected = true;
assert.equal(shared[0], shared[1]);
assert.equal(shared[1].selected, true);
console.log(shared.map(row => row.selected));
Phép thử cho ba giá trị true, vì cả ba vị trí trỏ đến cùng một object. Đây không phải map tự sửa cả array. Nếu factory trả lại một object đã tạo bên ngoài, ngay cả Array.from cũng có thể tạo cùng kiểu chia sẻ tham chiếu; vị trí tạo object mới mới là điểm quyết định.
Cách trả lời và kiểm tra trong dự án
Một câu trả lời đủ ý có thể bắt đầu từ length, chỉ ra hole khác undefined, rồi dùng phép đếm callback để chứng minh. Sau đó đề xuất Array.from cho khởi tạo và kiểm tra tính độc lập của object khi dữ liệu có thể thay đổi.
Không suy rằng mọi method array đều bỏ qua hole giống map. Khi thay method, đọc hợp đồng của method đó và viết fixture nhỏ với cả vị trí trống lẫn undefined. Bài không liệt kê toàn bộ hành vi sparse array của JavaScript và không đánh giá hiệu năng khởi tạo mảng lớn.
Trong code review, hỏi rõ mong muốn là N vị trí trống, N giá trị mặc định hay N object độc lập. Ba yêu cầu này gần nhau về hình thức nhưng dẫn đến lựa chọn triển khai khác nhau.


