views:

122

answers:

4

Hello.

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?

+1  A: 

I'm pretty sure this isn't a type problem, it's because IE didn't have the Array.map() function until IE 9, which hasn't released yet. 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
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
+1  A: 

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
+1  A: 

What happens is:

var arr = [1, 2, 3, 5, 7, 11];
var obj = {};

obj = arr;         // only copies a reference, no casting involved
alert(typeof arr); // object
alert(typeof obj); // object

If you want to check if something is an array you should do:

function isArray(obj) {
    return Object.prototype.toString.call(obj) === "[object Array]";
}

Which indirectly uses the [[Class]] internal property of an object.

galambalazs
`No casting involved` is slightly misleading, since by making that copy the `obj` goes from an `[object Object]` to an `[object Array]` (see the 3 alerts in my answer).
Peter Ajtai
+1  A: 

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
+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