将JavaScript对象转换为数组。如何操作?

28

我已经制作了这个沙盒测试:

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

我知道可以使用jQuery的$.map函数使这行代码工作,但是,在JavaScript数据类型方面我错过了什么?


我不太确定你想要实现什么。你是想要一个数组,其中每个索引代表对象的一个属性吗?还是一个对象,其中每个属性代表数组中的一个值? - bdukes
你总是会从 typeof 得到 object,因为数组只是带有数字属性、一些额外方法和一个神奇的 length 属性的对象。 - bdukes
6个回答

61

现代答案

如果您有一个可迭代对象,您可以使用展开运算符。

var a = [...o];

如果您有一个类似数组的对象(例如 arguments),您可以通过调用 Array.from(o) 来创建一个真正的数组。
var o = {0:"a", 1:'b', length:2};
var a = Array.from(o);

a 将会变成 ["a", "b"]。只有在正确设置了 length 属性时,这才能正常工作。


旧答案

如果你有一个类数组的对象(例如 arguments),你可以调用 Array.prototype.slice.call(o) 将其转换为一个真正的数组。

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

a 将会变成 ["a", "b"]。只有在正确设置了 length 属性时,这才能正常工作。


1
+1 - 这也是复制arguments数组的好方法,因为arguments.slice()不能用于arguments...而= arguments也没有帮助。http://jsfiddle.net/SMayA/ - Peter Ajtai
5
这个的速记方式是[].slice.call()。这是我从expressjs框架学到的。 - antitoxic
3
每次需要从原型中调用方法时创建新的数组有点浪费,不是吗? - AlexG
生成的数组是否仅包含符合 myobject.hasOwnProperty(mykey) 的元素? - ThorSummoner
@ThorSummoner:我不这么认为,但我认为它只会复制数字属性。如果你从原型继承数字属性,那么我认为你太聪明了。 - Sean McMillan

25

我认为你尽力了...

使用jQuery(或类似的库)最容易实现。

对于这个对象:

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

数组具有固定的键系统,因此对于上面的对象,您必须放弃键(a、b、c)或值(1、2、3)之一。

因此,要么这样:

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

或者这样:

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

2
该方法将删除空的“属性”。在我的情况下,我需要确保数组计数和项集合完全相等。 - hanzolo

7

9
变量u将成为一个只有一个元素的数组,该元素是对象t。我怀疑这是否符合需要的条件? - Jānis Elmeris
哇,詹尼斯,你说得对。那有什么意义呢?为什么不直接说[t]?!? - vbullinger
Janis,我花了一些时间在调试器上才意识到这一点......你是对的。 - Brice Coustillas

6

http://msdn.microsoft.com/en-us/library/s4esdbwz(v=VS.94).aspx 明确说明 Array.map() 函数是在 IE 9 中引入的。 - Mike Morearty

5

为了兼容各种浏览器,请使用 for 循环。

Javascript中,所有的数组都是对象,但并非所有对象都是数组。请查看 这个Perfection Kills页面,它描述了如何检查某个东西是否是一个数组。

要检查是否为数组,您可以使用 Object.prototype.toString.call(theObject)。对于一个数组对象,它将返回[object Array],而对于不是数组的对象,它将返回 [object Object] (请参见下面的示例):

            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


2

在许多其他用于操作对象和数组的小工具中,Underscore.js提供了一个toArray(obj)辅助方法。文档在这里:http://underscorejs.org/#toArray

从文档的写法上来看,它对任意对象都能正常工作,但事实上它会迭代对象的值并返回只包含这些值的列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接