Consider this piece of code, with console output at the end of each line:
function whatever() {
console.log(arguments) // { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
console.log(Array.prototype.slice.call(arguments)) // [ 1, 2, 3, 4, 5 ]
console.log(Array.prototype.slice.call({ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 })) // []
}
whatever(1,2,3,4,5)
Why is it that the third console.log outputs an empty array?
Because in order for Array.prototype.slice to work, you need to pass an array-like object. And in order for an object to fit that category, it needs a length property, which your object doesn't have. Try this:
var arr = { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 };
arr.length = 5;
var res = Array.prototype.slice.call(arr);
console.log(res);
FIDDLE
As @basilikum described, this is because .length is required in order to use .slice(). To understand why it's required, imagine that you were writing your own version of Array.prototype.slice() after reading the MDN docs:
Array.slice(begin[, end])
begin
Zero-based index at which to begin extraction.
As a negative index, begin indicates an offset from the end of the sequence. slice(-2) extracts the second-to-last element and the last element in the sequence.
end
Zero-based index at which to end extraction. slice extracts up to but not including end.
slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence.
If end is omitted, slice extracts to the end of the sequence.
To handle all those cases and a few more not listed, your code would have to be something along these lines (this may have bugs but should be close):
Array.prototype.myslice = function( begin, end ) {
// Use array length or 0 if missing
var length = this.length || 0;
// Handle missing begin
if( begin === undefined ) begin = 0;
// Handle negative begin, offset from array length
if( begin < 0 ) begin = length + begin;
// But make sure that didn't put it less than 0
if( begin < 0 ) begin = 0;
// Handle missing end or end too long
if( end === undefined || end > length ) end = length;
// Handle negative end (don't have to worry about < 0)
if( end < 0 ) end = length + end;
// Now copy the elements and return resulting array
var result = [];
for( var i = begin; i < end; ++i )
result.push( this[i] );
return result;
};
That's why .slice() requires this.length—you wouldn't be able to write the function without it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With