如何将迭代器(FormData)转换为对象

6
给定一个表单元素,new FormData(form) 返回一个迭代器。该迭代器可以遍历表单中包含的所有键值对。
// [["key1", "val1"],["key2", "val2"]]
console.log([new FormData(form)...])

我现在想将它转换为以下形式的对象:
{ "key1": "val1", "key2": "val2" }

使用 ES6/7 特性(由 babel 支持)。

你有没有任何想法可以用函数式方法实现这个吗?


我发现一个快速而不太规范的方法。该帖子中的方法似乎无法返回FormData对象的所有属性和值? - guest271314
@guest271314 你是对的 - 已经移除了 - bodokaiser
1
你知道,“对象字面量”是源代码中的文本。你可能想表达的是一个简单的对象。 - Musa
嗯,var o = {}; for (var [key, [o[key]] of formData.entries()); return o 应该可以。 - Bergi
它可能是 https://gist.github.com/lukehorvat/133e2293ba6ae96a35ba 最花哨的吗? - bodokaiser
@Bergi var o = {}; for (var [k, v, z = !(o[k] = v) || void 0] of formData); console.log(o, z) - guest271314
6个回答

8
你可以使用展开运算符...创建的Array来使用.reduce方法。
[...new FormData(document.querySelector('form'))].reduce((o, [k, v]) => {
    o[k] = v;
    return o;
}, {}); // Object {"key1": "val1", "key2": "val2"}

FormData 对象是可迭代的吗? - guest271314
1
@guest271314 https://xhr.spec.whatwg.org/#interface-formdata iterable<USVString, FormDataEntryValue>; - Paul S.
2
@guest271314:你在自己的回答中使用了for of来遍历一个FormData实例,现在问它是否可迭代? - Bergi
更加不可变且一行代码:[...formData].reduce((o, [k, v]) => ({...o, [k]:v}), {}); - ABCD.ca

4

你可以使用 Object.fromEntries(iterable);

来自文档:

参数:

iterable - 一个可迭代对象,如数组、映射或其他实现了可迭代协议的对象。

返回值:

一个新对象,其属性由可迭代对象的条目给出。

描述:

Object.fromEntries() 方法接受一组键值对,并返回一个新对象,该对象的属性由这些条目给出。可迭代参数应为一个实现了 @@iterator 方法的对象,该方法返回一个迭代器对象,该迭代器对象生成一个类似数组的两个元素的对象,其中第一个元素是将用作属性键的值,第二个元素是与该属性键关联的值。

const formData = new FormData();

formData.append("a", 111);
formData.append("b", 222);
formData.append("c", 333);

console.log(Object.fromEntries(formData))


3
您可以使用 for..of 循环。

var formData = new FormData();
formData.append("a", 123);
formData.append("b", 456);
var obj = {};
for(let prop of formData) {obj[prop[0]] = prop[1]};
console.log(obj)


Alternatively, using rest element, FormData() which returns an Iterator, Array.prototype.forEach().

var formData = new FormData();
formData.append("a", 123)
formData.append("b", 456)
var res = (d, it = [...d], r = {}, t =!(it.forEach(([k, v]) => {r[k] = v}))) => r;
console.log(res(formData))


使用 ... of formData.entries() 也不是错误的。更明确地说,有些人甚至认为这样做更好。 - Bergi
@Bergi一直在尝试使用var [...obj] = [...formData.entries()]; obj = obj.reduce(function(o, prop) { o[prop[1]] = prop[1] }, {}),不过将.reduce()部分合并到休息元素的第一部分中,或者直接赋值而不使用.reduce() - guest271314
1
[...obj] 没有意义,它等同于直接赋值给 obj。或者可以一次性使用 Array.from(formData.entries()).reduce(…) - Bergi

0
您可以简单地定义一个对象并循环遍历迭代器以从中获取值并将其分配给您创建的对象。
var fd = new FormData(someForm);
po = {};
for (var key of fd){
  po[key] = fd[key];
}

我认为你需要使用 fd.get(key)FormData 实例更像是一个 Map 而不是一个对象。 - Bergi
在发布之前,我已经在 Chrome 版本 50.0.2661.102 m (64 位) 中进行了测试。虽然我有一段时间没有尝试过,但我从未成功过 .get - Musa
嗯,迭代接口似乎很新。不确定 Chrome 实现了什么。 - Bergi

0

这是一个老问题,但最近我认为可以使用以下方法解决(以防有人发现它有用):

let fd = new FormData(form)...
console.log(Array.from(fd.entries()))

0

使用函数式编程方式

function getFormObj(form) {

 return  [...new FormData(form)].reduce((prev, [key,val]) => {
    return Object.assign(prev, {[key] : val}) ; 
  }, {}) ; 
}

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