使用ES6功能将对象转换为数组

79

如何在ECMAScript-6中将JavaScript对象转换为数组?

例如,给定:

 var inputObj = {a:'foo', b:[1,2,3], c:null, z:55};

预期输出应该是:

 ['foo', [1,2,3], null, 55]

对我来说,结果中元素的顺序并不重要。


1
我不确定你是否已经得到了你在这里寻找的答案? - Mritunjay
@Mritunjay 也许是一篇博客文章。 - user2864740
1
不,这样做没问题。这是一个不错的问题和不错的答案。虽然我希望它可以作为类似问题的答案添加,但它似乎不是针对es6特定的问题。 - technosaurus
1
我在这里放了一个jsperf:http://jsperf.com/objects-to-array/2 - technosaurus
使用 Object.values(inputObj)。 - v42
8个回答

123
使用(ES5)Array::maparrow function一起对keys进行操作(仅限于短语法,不包含功能):
let arr = Object.keys(obj).map((k) => obj[k])

真正的ES6风格是编写一个生成器,然后将其转换为可迭代的数组:

function* values(obj) {
    for (let prop of Object.keys(obj)) // own properties, you might use
                                       // for (let prop in obj)
        yield obj[prop];
}
let arr = Array.from(values(obj));

遗憾的是,没有任何object iterator被纳入ES6本地支持。


2
这种方法在这个测试案例中比老派的“for in”方法慢了大约85倍(是倍数,不是百分比)。在更大的数据集上,这种差异会显著改变吗? - technosaurus
你是怎么执行ES6的?你使用了什么测试数据,尝试过不同的大小吗?是的,map比循环稍微慢一些。 - Bergi
Firefox已经启用了它,Chrome需要chrome://flags/#enable-javascript-harmony。它可以运行,但在当前实现中速度非常慢。我猜忌对象迭代器被省略的原因是现有的JIT编译器已经可以识别旧方法中的这些模式。 - technosaurus
可能并不是 map 是慢的部分,而是由 Object.keys 创建的临时数组。如果您有一个不使用 Object.keys 的生成器函数,那么我期望它的速度会更接近于 for in - andy
1
@andy:再仔细看了一下,有一个名为Reflect.enumerate(obj)的函数可以完成功能。但我不知道它是否更快,特别是因为它似乎还没有在任何地方实现。顺便说一句,在V8中,Object.keys实际上非常快,有时比for in还要快。 - Bergi

64

只需使用Object.values即可。

Object.values(inputObj); // => ['foo', [1,2,3], null, 55]

1
轻松优雅,但这是esnext功能,所以您肯定需要寻找浏览器支持。 - Samiullah Khan
1
@Samiullah 现在每个人都在使用 Babel!特别是如果你正在使用 ES6 并关心浏览器兼容性。 - Fareed Alnamrouti

12

2020年8月更新

简而言之,在ES6中,将对象转换为数组有三种变化,如下所示:

const MyObjects = {   key1: 'value 1',   key2: 'value 2', };

// Method 1: Converts the keys to Array
// --------------------------------------

Object.keys(MyObjects);
// ['key1', 'key2']

// Method 2 Converts the Values to Array
// --------------------------------------

Object.values(MyObjects);
// ['value 1', 'value 2']

// Method 3 Converts both Values and Keys
// --------------------------------------

Object.entries(MyObjects);
// [ ['key1', 'value 1'], ['key2', 'value 2'] ]

将数组转换回对象可以按如下方式完成:

const array = [  ['one', 1],   ['two', 2], ];

Object.fromEntries(array);

// { one: 1, two: 2 }


11

我喜欢老派的方式:

var i=0, arr=[];
for (var ob in inputObj)
  arr[i++]=ob;

如果不考虑赞数,老派的方法在jsperf测试中大幅领先。有时候新加的功能反而是“误导性的特性”。


obj是什么,为什么ob是全局的? - Bergi
是的,但它仍然是一个全局变量。使用 for (let ob i inputObj) - Bergi
@technosaurus 我相信你在 for(var ob in inputObj) 中的变量 ob 应该是一个属性键。所以在循环内部,它应该是 arr[i++]=inputObj[ob];。这使得它比你现在拥有的代码慢22%。但它仍然比链接的jsperf中的其他代码快得多。 - jongo45

9
这可以通过使用数组推导语法来实现:
[for (key of Object.keys(inputObj)) inputObj[key]]

使用示例:

var inputObj = {a:'foo', b:[1,2,3], c:null, z:55};
var arr = [for (key of Object.keys(inputObj)) inputObj[key]];
console.log(arr);

// prints [ 'foo', [ 1, 2, 3 ], null, 55 ]

@Bergi 在数组解析语法中不起作用(至少在Tracuer中是如此) - urish
是的,显然只有迭代器应该在理解中使用。而且没有“Object”迭代器 - 你应该使用“Map”。 - Bergi
这在Chrome/Firefox上无法通过jsperf测试 http://jsperf.com/objects-to-array/2 我不知道该如何修复它。 - technosaurus
数组推导不是 ES7 吗? - bren
它们曾经在ES6中存在,但自那以后已被删除。根据https://github.com/tc39/ecma262的说法,它们似乎不会成为ES7的一部分。 - urish

9

ES7 的方法:

let obj = { a: "foo", b: "bar", c: 1, d: [1, 2, 3, 4] }

Object.values(obj)

// output --> ['foo', 'bar', 1, [1, 2, 3, 4]

请在这个仅包含代码的答案中添加一些解释。 - Yunnosch
当然可以,但是除了文档,没有什么需要解释的。Object.values()方法返回一个给定对象自己的可枚举属性值数组,顺序与for...in循环提供的相同(区别在于for-in循环也会枚举原型链中的属性)。 - Despertaweb
4
伙计,这是该方法的基本信息,这不是主题的目的。通过例子非常清楚明了。@Yunnosch - Despertaweb

5

Array.map等价于@Bergi的箭头函数(请参阅MDN了解有关Array.map的更多信息)。

2020年编辑:转换为片段并添加了另一种替代方案

const obj = {
    a: 'foo',
    b: [1, 2, 3],
    c: null,
    z: 55
  },
  nwArr = Object.keys(obj).map(k => obj[k]),
  // Alternative
  nwArr2 = Object.fromEntries(Object.entries(obj));
  nwArr.a = "bar";
  nwArr2.a = "foobar"
  console.log(`obj.a: ${obj.a}, nwArr.a: ${nwArr.a}, nwArr2.a: ${nwArr2.a}`);


3
更紧凑的代码版本:Object.values(obj) - leo

0
const address = {
        street: "bew1111",
        city: "err111",
        country: "ind11"
    };
    const address2 = {
        street: "bewscxsd",
        city: "errdc",
        country: "indcdsc"
    };

这里有两个对象,我将使用两种方法将这两个对象分配给数组

  1. Object.entries()

  2. Object.keys()

第一个从这里开始-----

var firstar = Object.entries(address);

这里我将地址分配给firstar,当您运行此代码时,您将获得以下输出

(3) [Array(2), Array(2), Array(2)]

第二个从这里开始

var secstar = Object.keys(address2);

我将address2分配给secstar,当您运行它时,将会得到以下输出

 (3) ["street", "city", "country"]

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