Problem
You want to create a generic function to convert array-like objects into arrays (see also recipe 2).
- Array-like objects
- An array-like object is an object, which behaves like an array, but which isn't one.
Array-like objects have a property
length
and elements can be accessed using indexes, but they typically don't have methods likeforEach()
etc. Two popular examples for array-like objects are instances ofNodeList
and thearguments
object.
Ingredients
- the
Array
prototype - the
slice()
method - the
call()
method - the
typeof
operator
Directions
-
Given: an array-like object that should be converted.
function someFunction() { var arrayLike = arguments; // An Array-like object var array = toArray(arrayLike); // Our goal: convert it to an array ... array.forEach(function(argument) { // ... so that we can apply array methods. console.log(argument); }); } someFunction(2,3,4,5,6,7);
-
Create a function
toArray()
that accepts an object.function toArray(object) { }
-
Now we need to check if the object is array-like. For that get the
length
property of the object …function toArray(object) { var length = object.length; }
-
… and check if the value associated with the
length
property is a number and not less than 0.function toArray(object) { var length = object.length; var isArrayLike = typeof length == 'number' && length >= 0; }
-
Optionally, but recommended: extract this code into a separate function
isArrayLike()
.function isArrayLike(object) { var length = object.length; return typeof length == 'number' && length >= 0; } function toArray(object) { if(isArrayLike(object)) { ... } }
-
Back in the
toArray()
method: borrow theslice()
method to convert the object into an array.function isArrayLike(object) { var length = object.length; return typeof length == 'number' && length >= 0; } function toArray(object) { if(isArrayLike(object)) { return Array.prototype.slice.call(object); } }
-
Before checking if the object is array-like it makes sense to check if the object is already an array (using
Array.isArray()
).function isArrayLike(object) { var length = object.length; return typeof length == 'number' && length >= 0; } function toArray(object) { if(Array.isArray(object)) { return object; } else if(isArrayLike(object)) { return Array.prototype.slice.call(object); } }
-
If the object is neither an array nor array-like: throw an error.
function isArrayLike(object) { var length = object.length; return typeof length == 'number' && length >= 0; } function toArray(object) { if(Array.isArray(object)) { return object; } else if(isArrayLike(object)) { return Array.prototype.slice.call(object); } else { throw new TypeError('Argument could not be converted.'); } }
-
Voilá, a tasteful helper function for converting array-like objects into arrays (and one for testing if an object is array-like).
function isArrayLike(object) { var length = object.length; return typeof length == 'number' && length >= 0; } function toArray(object) { if(Array.isArray(object)) { return object; } else if(isArrayLike(object)) { return Array.prototype.slice.call(object); } else { throw new TypeError('Argument could not be converted.'); } } function someFunction() { var arrayLike = arguments; // Array-like object var array = toArray(arrayLike); // Convert to array array.forEach(function(argument) { // Apply array method console.log(argument); }); } someFunction(2,3,4,5,6,7);
Alternative recipes
- Instead of using the
arguments
object use rest parameters (see also recipe 2).