深入解析 JavaScript FormData 对象
FormData 是浏览器内置的 API,用于构造一组键值对来表示表单字段。它最常见的应用场景是文件上传,配合 multipart/form-data 编码类型,可以实现与服务器端的流式数据传输。
构造函数接受两个可选参数:
form:HTML 表单元素submitter:触发提交的按钮元素
const fd = new FormData();
核心方法详解
1. append 与 set
append(name, value) 用于添加数据,当同名键存在时不会覆盖,而是新增一条记录。这与普通对象的行为截然不同——FormData 允许一个键对应多个值。
const fd = new FormData();
fd.append('tag', 'javascript');
fd.append('tag', 'typescript');
fd.append('tag', 'node');
set(name, value) 同样用于添加数据,但如果键已存在,会移除该键的所有旧值后再写入新值。
const fd = new FormData();
fd.set('status', 'active');
fd.set('status', 'inactive'); // 最终仅剩 'inactive'
fd.append('count', '5');
fd.set('count', '10'); // 覆盖为单个值 '10'
2. 数据读取:get 与 getAll
const fd = new FormData();
fd.append('score', '85');
fd.append('score', '92');
console.log(fd.get('score')); // "85"
console.log(fd.getAll('score')); // ["85", "92"]
fd.set('score', '100');
console.log(fd.getAll('score')); // ["100"]
3. 存在性检测:has
const fd = new FormData();
fd.append('id', '007');
console.log(fd.has('id')); // true
console.log(fd.has('password')); // false
4. 删除数据:delete
该方法会彻底清除指定键的所有条目,无论该键存在多少条记录。
const fd = new FormData();
fd.append('temp', 'a');
fd.append('temp', 'b');
fd.delete('temp');
console.log(fd.getAll('temp')); // []
5. 迭代器方法
FormData 实现了 Iterable 接口,提供了三种获取遍历器的方式:
const fd = new FormData();
fd.append('lang', 'rust');
fd.set('year', '2024');
// 获取所有键
const allKeys = [...fd.keys()];
console.log(allKeys); // ["lang", "year"]
// 获取所有值
const allValues = [...fd.values()];
console.log(allValues); // ["rust", "2024"]
// 获取键值对
const pairs = [...fd.entries()];
console.log(pairs); // [["lang", "rust"], ["year", "2024"]]
进阶特性
原生遍历支持
由于实现了 Symbol.iterator,FormData 可直接用于 for...of 循环,也可用展开运算符处理。默认迭代行为与 entries() 一致。
const fd = new FormData();
fd.append('framework', 'react');
fd.append('framework', 'vue');
for (const entry of fd) {
console.log(entry);
}
// 输出: ["framework", "react"]
// ["framework", "vue"]
console.log([...fd]); // 等价于 [...fd.entries()]
转换为普通对象
借助 Object.fromEntries 可实现转换,但需注意:对象键的唯一性会导致同键多值的情况丢失数据。
const fd = new FormData();
fd.append('category', 'frontend');
fd.append('category', 'backend');
fd.set('name', 'dashboard');
const plain = Object.fromEntries(fd);
console.log(plain);
// { category: "backend", name: "dashboard" }
// 注意: "frontend" 已丢失
生成 URL 查询字符串
FormData 可作为 URLSearchParams 的构造参数,快速生成编码后的查询字符串。此特性适用于需要兼容传统表单提交的场景。
const fd = new FormData();
fd.append('keyword', 'webassembly');
fd.append('page', '3');
const qs = new URLSearchParams(fd).toString();
console.log(qs); // "keyword=webassembly&page=3"
需注意的是,当同一键存在多个值时,查询字符串会保留重复参数,服务端需按相应规则解析。