JavaScript: How to Convert Array-Like Object to Array?

By Xah Lee. Date: . Last updated: .

How to convert a array-like object to array?

Like this: Array.prototype.slice.call(array-like_object).

// create a array-like object
var aa = {0:"a", 1:"b",2:"c", length:3};

// convert to array
var bb = Array.prototype.slice.call(aa);

console.log(
    Array.isArray(aa) // false
)

console.log(
    Array.isArray(bb) // true
)

console.log(aa); // { '0': 'a', '1': 'b', '2': 'c', length: 3 }
console.log(bb); // [ 'a', 'b', 'c' ]

How does this work?

The array method myArray.slice(…) with no argument will just make a shallow copy (and returns a array). We want to use this method on our array-like object alo. 〔►see JavaScript: Array.prototype

By spec, the array method obj.slice() works by setting the function's keyword this to obj, then goes thru the object's numerical index or properties. So, that means it will also work with array-like objects. 〔►see JavaScript: What's Array-Like Object?〕 〔►see JavaScript: Keyword “this”

The problem is, alo isn't a array, so it doesn't inherit method “slice” from array object. What to do?

Array methods are properties of Array.prototype. So, “slice” can be accessed by calling Array.prototype.slice(…).

The problem is, slice(…) doesn't take a object as argument. Its only args are start/end indexes, for example: a_array.slice(start, end). How can we call “slice” by Array.prototype.slice() yet passing it alo instead Array.prototype?

This can be solved in general using the “call” method from “Function.prototype”. Like this function_name.call(alo, args).

So, we can do Array.prototype.slice.call(alo). 〔►see JavaScript: Function Call, Apply, Bind

Why can we use “Array.prototype.slice.call” while it's actually “Function.prototype.call”? Because “slice(…)” is a function, so it inherits “call” from Function.prototype. This is why we can write Array.prototype.slice.call(…).

Here's a fuller explanation with code.

// the object 「Array」 is a standard object, and is a function object
console.log(
    typeof Array === "function"
); // true

// Array has a property key "prototype"
// every function has a property key "prototype", by spec.
console.log(
    Object.prototype.hasOwnProperty.call(Array,"prototype")
); // true

// the value of Array.prototype, is a object, and the only way to express it is just Array.prototype

// This object Array.prototype, is the parent of array data type object, by spec.
console.log(
    Object.getPrototypeOf([]) === Array.prototype
); // true

// This object Array.prototype has a property key "slice"
console.log(
    Array.prototype.hasOwnProperty("slice")
); // true

// its value is a function
console.log(
    typeof Array.prototype.slice === "function"
); // true

// the parent of Array.prototype.slice is Function.prototype
console.log(
    Object.getPrototypeOf(Array.prototype.slice) === Function.prototype
); // true

// Function.prototype has a property key "call"
console.log(
    Function.prototype.hasOwnProperty("call") &&
    (Object.getOwnPropertyNames(Function.prototype).indexOf("call") >= 0)
); // true

// so when eval Array.prototype.slice.call, it's actually calling the value of the property key "call" of the object Function.prototype. Because, the property is in the prototype chain.

// what the 「‹f›.call(‹obj›)」 do is to call ‹f› with ‹f›'s 「this」 value set to 「obj」

To really understand it, read the following in order.

  1. JavaScript: Prototype and Inheritance
  2. JavaScript: Keyword “this”
  3. JavaScript: Function Call, Apply, Bind

Should You Convert a Array-Like Object to Array?

You almost NEVER need to convert a array-like object to true array, because, you can always use array methods on array-like objects.

You can use Array Methods directly by calling Array.prototype.array_method_name.call(array_like_obj, args).

〔►see JavaScript: Function Call, Apply, Bind

// using map directly on array-like object

// create a array-like object
var alo = {0:"a", 1:"b", 2:"c", length:3};

// the function you want to apply to array-like object's elements
function append_z_to_string (x) {return x + "z"; }

// using map on a array-like object
var myResult = Array.prototype.map.call( alo, append_z_to_string);

// result is a array
console.log(
    Array.isArray(myResult) // true
)

console.log(myResult); // [ 'az', 'bz', 'cz' ]

Array Topic

  1. JavaScript: Array Basics
  2. JavaScript: Understand JS Array
  3. JavaScript: Create Array
  4. JavaScript: Sparse Array
  5. JavaScript: What's Array-Like Object?
  6. JavaScript: How to Convert Array-Like Object to Array?
  7. JavaScript: Array How-To

  1. JavaScript: Array Object
  2. JavaScript: Array.prototype
Like what you read? Buy JavaScript in Depth
or, buy a new keyboard, see Keyboard Reviews.