28

I have made this sandbox test:

<html>
    <head>
        <title>whatever</title>
        <script type="text/javascript">
            function myLittleTest() {
                var obj, arr, armap;

                arr = [1, 2, 3, 5, 7, 11];

                obj = {};
                obj = arr;
                alert (typeof arr);
                alert (typeof obj);

                // doesn't work in IE
                armap = obj.map(function (x) { return x * x; });
                alert (typeof armap);

            }
            myLittleTest();
        </script>
    </head>
    <body>
    </body>
</html>

I realize I can use jQuery's function $.map for making that line of code work, but, what am I missing on javascript datatypes?

Jhonny D. Cano -Leftware-
  • 17,663
  • 14
  • 81
  • 103
  • I'm not really sure what you're trying to accomplish. Do you want an array where each index represents a property from and object? Or an object where each property represents a value from the array? – bdukes Oct 05 '10 at 15:32
  • You're always going to get `object` from `typeof` for arrays. Arrays are just objects with numeric properties, a few extra methods, and a magic `length` property. – bdukes Oct 05 '10 at 15:34

6 Answers6

60

Modern Answer

If you have an iterable, you can use the spread operator.

var a = [...o];

If you have an array-like object, (like arguments, for example,) you can get a real array made from it by calling Array.from(o).

var o = {0:"a", 1:'b', length:2};
var a = Array.from(o);

a will be ["a", "b"]. This will only work right if you have a correctly set length property.


Older Answer

If you have an array-like object, (like arguments, for example,) you can get a real array made from it by calling Array.prototype.slice.call(o).

var o = {0:"a", 1:'b', length:2};
var a = Array.prototype.slice.call(o);

a will be ["a", "b"]. This will only work right if you have a correctly set length property.

Sean McMillan
  • 10,058
  • 6
  • 55
  • 65
  • 1
    +1 - This is also a great way to make a copy of the `arguments` array, since `arguments.slice()` doesn't work on `arguments`... and `= arguments` isn't helpful. http://jsfiddle.net/SMayA/ – Peter Ajtai Oct 05 '10 at 17:46
  • 5
    A shorthand for this would be `[].slice.call()`. This is something I learned from expressjs framework. – antitoxic Oct 12 '12 at 19:39
  • 3
    It's a bit wasteful though, creating a new Array everytime you need to call a method from its prototype? – AlexG May 01 '13 at 07:24
  • Will the resulting array consist only of elements that qualify for `myobject.hasOwnProperty(mykey)` ? – ThorSummoner Mar 12 '15 at 20:42
  • @ThorSummoner: I don't think so, but I think it will only copy numeric properties. If you're inheriting numeric properties from your prototype, you're too clever, I think. – Sean McMillan Mar 13 '15 at 02:13
25

I think you are trying too hard...

It's easiest with jQuery (or similar library)

For this object:

var obj = {a: 1, b: 2, c: 3};

Arrays have a fixed key system so for the object above, you've got to throw away either the keys (a, b, c) or the values (1, 2, 3)

So either this:

var arr = $.map(obj, function (value, key) { return value; });

or this:

var arr = $.map(obj, function (value, key) { return key; });
Taryn
  • 242,637
  • 56
  • 362
  • 405
Matthew Baker
  • 251
  • 3
  • 2
  • 2
    This method will remove null "properties". In my case i need the array count and item collection to be exactly equal – hanzolo Jan 17 '13 at 01:29
7

A year ago now, but I may as well mention jQuery's makeArray function http://api.jquery.com/jQuery.makeArray/

Adaddinsane
  • 535
  • 6
  • 11
6

I'm pretty sure this isn't a type problem, it's because IE didn't have the Array.map() function until IE 9. See http://msdn.microsoft.com/en-us/library/k4h76zbx(v=VS.85).aspx for a list of supported functions. See http://msdn.microsoft.com/en-us/library/ff679976(v=VS.94).aspx for a description of the Array.map() function in IE 9.

Mike Morearty
  • 9,953
  • 5
  • 31
  • 35
  • http://msdn.microsoft.com/en-us/library/s4esdbwz(v=VS.94).aspx clearly states that the `Array.map()` function was introduced in IE 9. – Mike Morearty Oct 05 '10 at 15:34
5

Use a for loop for max browser compatibility.

In Javascript all arrays are objects, but not all object are arrays. Take a look at this Perfection Kills page which describes how to check that something is an Array.

To check for an array, you can use Object.prototype.toString.call(theObject). This will return [object Array] for an object that is an Array and [object Object] for an object that's not an Array (see example below):

            function myLittleTest() 
            {
                var obj, arr, armap, i;    

                  // arr is an object and an array
                arr = [1, 2, 3, 5, 7, 11]; 

                obj = {}; // obj is only an object... not an array

                alert (Object.prototype.toString.call(obj));
                  // ^ Output: [object Object]

                obj = arr; // obj is now an array and an object

                alert (Object.prototype.toString.call(arr));
                alert (Object.prototype.toString.call(obj));
                  // ^ Output for both: [object Array]

                // works in IE
                armap = [];
                for(i = 0; i < obj.length; ++i)
                {
                    armap.push(obj[i] * obj[i]);
                }

                alert (armap.join(", ")); 

            }
            // Changed from prueba();
            myLittleTest();

jsFiddle example

Peter Ajtai
  • 56,972
  • 13
  • 121
  • 140
2

Among many other small utilities for manipulating objects and arrays, Underscore.js offers a toArray(obj) helper method. Documentation here: http://underscorejs.org/#toArray

It's not totally obvious from the way the documentation is written, but it works like a charm on arbitrary objects. When given an object, it iterates over the values and returns a list that contains just those values.

drewww
  • 2,485
  • 4
  • 22
  • 24