Biểu mẫu tạo ba dòng trống; sửa nhãn dòng đầu thì cả ba dòng cùng đổi. Lỗi có thể xuất phát từ new Array(3).fill({ ... }): fill nhận một object rồi gán cùng tham chiếu đó vào nhiều vị trí, không tạo ba object độc lập.
Bài viết tập trung vào khởi tạo dữ liệu trong bộ nhớ. Dữ liệu nhìn giống nhau khi mới tạo chưa chứng minh các phần tử độc lập; cần kiểm tra cả tham chiếu và hành vi sau khi sửa.
1. fill object tạo nhiều đường dẫn tới cùng dữ liệu
const rows = new Array(3).fill({ label: '' });
rows[0].label = 'Ready';
console.log(rows[0] === rows[1]); // true
console.log(rows.map(row => row.label).join(',')); // Ready,Ready,Ready
Object literal được tạo trước khi fill chạy. Phương thức dùng chính giá trị đó cho mọi vị trí trong phạm vi cần điền. Vì vậy sửa label qua rows[0] cũng được nhìn thấy qua rows[1] và rows[2].
Đây không phải lỗi của component giao diện. Nếu dữ liệu nền dùng chung tham chiếu, thay đổi cách render mà không sửa cách khởi tạo có thể chỉ che biểu hiện.
2. Đặt việc tạo object bên trong callback
const rows = Array.from({ length: 3 }, (_, index) => ({
id: index,
label: '',
settings: { enabled: false }
}));
rows[0].label = 'Ready';
rows[0].settings.enabled = true;
console.log(rows[0] === rows[1]); // false
console.log(rows[0].settings === rows[1].settings); // false
console.log(rows[1].label === ''); // true
console.log(rows[1].settings.enabled); // false
Callback tạo object mới cho từng phần tử, gồm cả settings lồng bên trong. Nếu đưa settings ra biến dùng chung ở ngoài rồi gán vào mỗi dòng, tầng đó vẫn có thể chia sẻ tham chiếu dù object ngoài đã khác nhau.
id theo index chỉ dùng cho dữ liệu minh họa, không phải ID nghiệp vụ ổn định cho danh sách có thể chèn hoặc sắp xếp lại. Chọn định danh phù hợp khi đưa vào ứng dụng.
3. Ma trận cũng có bẫy dùng chung hàng
const shared = new Array(2).fill(new Array(2).fill(0));
shared[0][0] = 9;
console.log(JSON.stringify(shared)); // [[9,0],[9,0]]
const independent = Array.from({ length: 2 }, () =>
new Array(2).fill(0)
);
independent[0][0] = 9;
console.log(JSON.stringify(independent)); // [[9,0],[0,0]]
Ở phiên bản đầu, hai hàng trỏ tới cùng một mảng. Ở phiên bản sau, callback tạo mảng hàng mới mỗi lần. Điền 0 vào từng hàng phù hợp vì 0 là giá trị nguyên thủy.
Nếu mỗi ô lại là object, new Array(2).fill({ value: 0 }) vẫn dùng chung object trong hàng. Cần tạo riêng ở đúng tầng cần độc lập, không chỉ sửa tầng ngoài.
4. fill sửa mảng đang có
const values = [1, 2, 3, 4];
const returned = values.fill(0, 1, 3);
console.log(returned === values); // true
console.log(JSON.stringify(values)); // [1,0,0,4]
Phạm vi bắt đầu tại start và dừng trước end. Kết quả trả về là chính mảng đã sửa, không phải bản sao. Nếu nơi khác đang giữ values, nó cũng thấy thay đổi này.
Khi chỉ cần tạo một danh sách số mặc định mới, fill là lựa chọn rõ ràng. Khi cần giữ nguyên nguồn, tạo mảng mới có chủ đích trước khi điền và xem lại các tham chiếu object nếu có.
5. Giới hạn kích thước trước khi cấp phát
function createRows(count) {
if (!Number.isInteger(count) || count < 0 || count > 1000) {
throw new RangeError('Expected an integer from 0 to 1000');
}
return Array.from({ length: count }, () => ({
label: '',
settings: { enabled: false }
}));
}
console.log(createRows(0).length); // 0
const rows = createRows(2);
console.log(rows[0].settings === rows[1].settings); // false
Giới hạn 1000 là chính sách minh họa cho một danh sách nhỏ. Nó không phải ngưỡng hiệu năng chung của JavaScript. Với đầu vào từ bên ngoài, xác nhận kiểu và miền trước khi tạo mảng; không để một số lượng không kiểm soát quyết định mức cấp phát.
Hàm tạo mới những trường đã biết. Nó không phải thuật toán clone sâu cho template tùy ý. Với dữ liệu phức tạp, hãy định nghĩa cách tạo từng tầng hoặc cơ chế sao chép phù hợp với kiểu dữ liệu thực tế.
6. Kiểm thử độc lập bằng cách sửa một phần tử
- Số phần tử bằng kích thước yêu cầu, gồm 0 và 1.
- Hai object ngoài khác tham chiếu khi yêu cầu độc lập.
- Object lồng hoặc hàng ma trận cũng khác tham chiếu.
- Sửa dòng hoặc ô đầu không làm đổi hàng xóm.
- fill trên mảng đang có được nhận diện là thao tác thay đổi nguồn.
- Số âm, số lẻ, chuỗi số và giá trị vượt giới hạn bị xử lý theo contract.
Các đoạn code đã chạy bằng Node.js local, gồm kiểm tra bổ sung tính độc lập của nhiều dòng và giới hạn count. Chưa kiểm thử biểu mẫu trình duyệt hoặc đo hiệu năng. Tài liệu đối chiếu: Array.prototype.fill và Array.from.
Muốn nhiều phần tử độc lập, hãy tạo giá trị mới ở từng lần gọi factory. Một mảng có nhiều vị trí chưa có nghĩa nó chứa nhiều object khác nhau.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.