Converting objects to arrays using Array.prototype.slice.call()
Last updated: Sept 25th, 2014
A line you may have encountered every now and then inside some JavaScript functions looks like this:
Array.prototype.slice.call(arguments, 1)
And just when you think you've finally gotten a handle on the
language, cryptic lines like the above shake your confidence, as JavaScript
often will do. In this short tutorial, lets elaborate on the subject line
and delve into just what Array.prototype.slice.call()
is, works, and how its
useful.
Arrays versus array-like objects
In JavaScript, there are arrays, then there are array-like
objects. The later is any object with a "length
" property that
returns the
number of elements inside the object, plus numeric indices giving access to
elements inside it. Examples of this include the arguments array of
a function, HTMLCollection collections, and custom objects with a length
property and numeric indices. The following are all array-like objects in JavaScript:
function myfunc(){ var args = arguments // array-like collection for (var i=0; i<arguments.length; i++){ //do something with each argument/parameter passed into function } }
var uls = document.getElementsByTagName("ul") // array-like collection
var myobject ={ // array-like collection length: 4, '0': 'zero', '1': 'one', '2': 'two', '3': 'three' }
While such objects may appear to be arrays in that individual elements within it can be accessed numerically, for example
arguments[0] // access first argument within arguments array uls[2] // access 3rd UL on the page myobject.length // returns 4
A quick test for "arrayness" on any of them shatters that illusion:
if (Array.isArray(uls)){ // Returns false. isArray() is supported in IE9+, Firefox1.5+ Chrome, Safari and Opera 10.5+ //do something }
The difference between an array and an object masquerading
as one lies in the
extensive list of useful methods the former has at its disposal, which
at times surely can come in handy when working with the later as well. And
that's where the cryptic Array.prototype.slice.call
comes in.
Using Array.prototype.slice.call to convert Array-like objects into real arrays
Array.prototype.slice.call()
serves as a quick
way to turn any array-like object into a true array. Most of us are already
familiar with Array's slice(start, [end])
method to return a
"slice" of an array:
["zero", "one", "two", "three"].slice(1) // returns "one", "two", "three" ["zero", "one", "two", "three"].slice(0, 2) // returns "zero", "one"
The slice()
method in this case belongs to the
Array object (its "this
" object points to our array instance).
By calling the slice()
method as a method of the desired
array-like object instead, that process coerces the later into a true array
at the same time. And thankfully JavaScript makes it easy to do just that,
invoke a method as if it belongs to a different host function, via the
call()
and apply()
methods. When we invoke a method this way, the
resulting "this
" object points not to the original function
associated with it, but the new function.
Armed with this knowledge, we are half way to understanding why the following works in converting an array-like object into a true array:
var myobject ={ // array-like collection length: 4, '0': 'zero', '1': 'one', '2': 'two', '3': 'three' } var myarray = Array.prototype.slice.call(myobject) // returns myobject as a true array: ["zero", "one", "two", "three"]
And since the slice()
method supports optional
"start" and "end" parameters to return just a portion of an array as a new
array, we can do the following:
var myarray = Array.prototype.slice.call(myobject, 1) // returns ["one", "two", "three"]
var myarray = Array.prototype.slice.call(myobject, 0, 2) // returns ["zero", "one"]
The one remaining question is why we're calling
slice()
on the prototype object of Array instead of an array
instance. The reason is because this is the most direct route to accessing
the slice()
method of Array when that's all we're interested
in; we could have first created an array instance, but that's less efficient
and arguably more abstruse:
var myarray = new Array().prototype.slice.call(myobject) // less efficient
Now that we've demystified Array.prototype.slice.call()
,
lets peer into the not so distant future where a more official way of
converting array-like objects into arrays exists, and that is
Array.from()
.
- Converting objects to arrays using Array.prototype.slice.call()
- Converting array-like objects into arrays using Array.from() method (ECMAScript 6)
Converting array-like objects into arrays using Array.from() method (ECMAScript 6)