Assigning length to limit a list can remove the tail of the source array. Array.length is writable, not merely a count to read. Establish who shares the array and whether the goal is data mutation or partial presentation before changing it.
1. Shrinking length mutates the same array
const rows = ['A', 'B', 'C', 'D'];
const shared = rows;
rows.length = 2;
console.log(JSON.stringify(rows)); // ["A","B"]
console.log(JSON.stringify(shared)); // ["A","B"]
rows.length = 4;
console.log(Object.hasOwn(rows, 2)); // false
These are ordinary arrays with deletable elements. C and D disappear after truncation; growing length again does not restore them. shared observes the change because it references the same array.
A table's presentation limit should not discard source data still needed elsewhere. A const binding does not prevent mutation of the referenced array.
2. Growing length does not create records
const rows = ['A'];
rows.length = 3;
let calls = 0;
rows.map(value => {
calls += 1;
return value;
});
console.log(rows.length); // 3
console.log(calls); // 1
console.log(Object.hasOwn(rows, 1)); // false
The example has length 3 but only one present element for map to visit. New positions are empty slots. See MDN Array.length for length changes and sparse arrays.
Create explicit placeholder values if the UI requires three placeholder records. Do not interpret length as evidence that three records were loaded and validated.
3. Assignment is not input validation
const rows = ['A', 'B', 'C'];
rows.length = '2';
console.log(JSON.stringify(rows)); // ["A","B"]
try {
rows.length = 1.5;
} catch (error) {
console.log(error instanceof RangeError); // true
}
console.log(rows.length); // 2
The numeric string truncates this array, while a fractional length is rejected. Trying an assignment and checking for exceptions is therefore insufficient validation for an application's pagination parameter.
Define conversion and business limits at the input boundary. Reporting invalid data before mutation avoids accidentally truncating the source.
4. Take a prefix without mutating the source array
function takeFirst(items, limit) {
if (!Array.isArray(items)) throw new TypeError('items must be an array');
if (!Number.isInteger(limit) || limit < 0 || limit > 1000) {
throw new RangeError('limit must be an integer from 0 to 1000');
}
return items.slice(0, limit);
}
const rows = [{ id: 'A' }, { id: 'B' }, { id: 'C' }];
const visible = takeFirst(rows, 2);
console.log(visible.length); // 2
console.log(rows.length); // 3
console.log(visible[0] === rows[0]); // true
The maximum of 1000 is this helper's example policy, not an Array limit. Zero produces an empty array; a limit above the existing count takes at most the available prefix. Individual record schemas remain unchecked.
slice creates a new array with a shallow copy; see MDN slice. The final comparison demonstrates shared object references. Mutating visible[0].id can still affect rows[0]. Sparse input also remains sparse.
5. Review data ownership and shared references
- Is the goal mutation or a separate presentation list?
- Who else references the same source array?
- Are added positions empty slots or actual values?
- Is the limit validated against the product contract?
- Do tests inspect source arrays and nested objects?
All eight bilingual blocks ran with Node.js, alongside boundary-limit, invalid-input and source-preservation checks. Real UI and API integration were not tested.




No comments yet. Be the first to share your thoughts.