JS `Object.fromEntries()`:将 `Map` 或键值对数组转换为对象

嘿,大家好!今天我们来聊聊 JavaScript 中一个相当实用,但可能被很多人忽略的小可爱:Object.fromEntries()。这玩意儿能把 Map 对象或者键值对数组,“唰”的一下变成一个普通 JavaScript 对象。听起来是不是有点像变魔术?

咱们先来明确一下,为啥我们需要这种“变身术”?

为啥我们需要 Object.fromEntries()

在 JavaScript 的世界里,对象(Object)无疑是最核心的数据结构之一。但有时候,我们手头上的数据并不是对象的形式,而是像 Map 或者键值对数组这样“奇形怪状”的。这时,Object.fromEntries() 就派上大用场了。

  1. 处理 Map 对象: Map 对象允许我们使用任何类型的值作为键,这在某些情况下非常方便。但如果我们最终需要一个普通对象,比如要把它传递给一个只接受对象的库,或者需要在 JSON 中序列化它,Object.fromEntries() 就能帮我们轻松搞定。

  2. 处理键值对数组: 有些 API 返回的数据格式是键值对数组,而不是一个对象。例如,URLSearchParams 对象就提供了一个 entries() 方法,返回一个键值对迭代器。我们可以用 Object.fromEntries() 把这些数据直接转换为对象,省去了手动构建对象的麻烦。

  3. 简化代码: 在某些情况下,使用 Object.fromEntries() 可以使我们的代码更简洁、更易读。

Object.fromEntries() 的基本用法

Object.fromEntries() 接受一个可迭代对象作为参数,这个可迭代对象需要产生键值对。换句话说,它需要返回形如 [key, value] 的数组。

const entries = [
  ['name', 'Alice'],
  ['age', 30],
  ['city', 'New York']
];

const obj = Object.fromEntries(entries);

console.log(obj); // 输出: { name: 'Alice', age: 30, city: 'New York' }

是不是很简单?我们把一个键值对数组传递给 Object.fromEntries(),它就返回了一个包含这些键值对的对象。

Map 对象变身

接下来,我们看看如何把 Map 对象转换为普通对象。

const map = new Map([
  ['name', 'Bob'],
  ['occupation', 'Engineer'],
  ['country', 'USA']
]);

const obj = Object.fromEntries(map);

console.log(obj); // 输出: { name: 'Bob', occupation: 'Engineer', country: 'USA' }

同样非常简单!Map 对象本身就是一个可迭代对象,它会产生键值对,所以可以直接传递给 Object.fromEntries()

URLSearchParams 的妙用

URLSearchParams 对象用于解析和操作 URL 查询字符串。它的 entries() 方法返回一个键值对迭代器,我们可以用 Object.fromEntries() 将其转换为对象。

const paramsString = 'name=Charlie&age=25&city=London';
const searchParams = new URLSearchParams(paramsString);

const paramsObj = Object.fromEntries(searchParams.entries());

console.log(paramsObj); // 输出: { name: 'Charlie', age: '25', city: 'London' }

这个例子展示了如何从 URL 查询字符串中提取参数,并将其转换为一个方便的对象。

进阶用法:处理特殊情况

虽然 Object.fromEntries() 很方便,但也有一些需要注意的地方。

  1. 重复的键: 如果可迭代对象中包含重复的键,后面的键值对会覆盖前面的。
const entries = [
  ['name', 'David'],
  ['age', 40],
  ['name', 'Eve'] // 重复的键 'name'
];

const obj = Object.fromEntries(entries);

console.log(obj); // 输出: { name: 'Eve', age: 40 }

可以看到,最后的 name 变成了 ‘Eve’,覆盖了之前的 ‘David’。

  1. 键的类型: Object.fromEntries() 会将所有的键都转换为字符串。即使键是数字或其他类型,也会被强制转换为字符串。
const entries = [
  [1, 'One'],
  [true, 'True'],
  [null, 'Null']
];

const obj = Object.fromEntries(entries);

console.log(obj); // 输出: { '1': 'One', 'true': 'True', 'null': 'Null' }
  1. 空值和 undefined 如果可迭代对象中包含 nullundefined 作为值,它们会被保留在对象中。
const entries = [
  ['name', 'Frank'],
  ['age', null],
  ['city', undefined]
];

const obj = Object.fromEntries(entries);

console.log(obj); // 输出: { name: 'Frank', age: null, city: undefined }
  1. 处理复杂数据结构: 如果值本身是一个对象或者数组,Object.fromEntries() 会直接将该对象或数组放入新对象中,而不会进行深拷贝。
const entries = [
    ['person', {name: 'Grace', age: 35}],
    ['hobbies', ['reading', 'coding']]
];

const obj = Object.fromEntries(entries);

console.log(obj); // 输出: { person: { name: 'Grace', age: 35 }, hobbies: [ 'reading', 'coding' ] }

修改 obj.person.name 也会影响到原始对象。

与其他方法的比较:Object.entries()reduce()

了解了 Object.fromEntries(),我们再来看看其他一些相关的 JavaScript 方法,以便更好地理解它的优势和适用场景。

  1. Object.entries() 它是 Object.fromEntries() 的反向操作。Object.entries() 接受一个对象作为参数,返回一个包含键值对的数组。
const obj = {
  name: 'Henry',
  age: 28,
  country: 'Canada'
};

const entries = Object.entries(obj);

console.log(entries);
// 输出:
// [
//   ['name', 'Henry'],
//   ['age', 28],
//   ['country', 'Canada']
// ]

Object.entries()Object.fromEntries() 就像一对好基友,经常一起出现,用于在对象和键值对数组之间进行转换。

  1. reduce() 我们可以使用 reduce() 方法来手动构建对象,实现与 Object.fromEntries() 类似的功能。
const entries = [
  ['name', 'Ivy'],
  ['age', 32],
  ['city', 'Sydney']
];

const obj = entries.reduce((acc, [key, value]) => {
  acc[key] = value;
  return acc;
}, {}); // {} 是初始值,一个空对象

console.log(obj); // 输出: { name: 'Ivy', age: 32, city: 'Sydney' }

虽然 reduce() 可以实现相同的功能,但相比之下,Object.fromEntries() 的代码更简洁、更易读。

Object.fromEntries() 的优势

  • 简洁性: Object.fromEntries() 的语法非常简洁,可以大大减少代码量。
  • 可读性: 使用 Object.fromEntries() 可以使代码更易于理解,因为它明确表达了“从键值对数组创建对象”的意图。
  • 语义化: Object.fromEntries() 提供了更语义化的方式来处理键值对数组和对象之间的转换。

使用场景示例

使用场景 描述 代码示例
Map 对象转换为普通对象 当需要将 Map 对象传递给只接受普通对象的函数或库时。 javascript <br>const map = new Map([['a', 1], ['b', 2]]);<br>const obj = Object.fromEntries(map);<br>console.log(obj); // { a: 1, b: 2 }<br>
处理 URLSearchParams 从 URL 查询字符串中提取参数并转换为对象。 javascript<br>const url = 'https://example.com?name=John&age=30';<br>const params = new URLSearchParams(new URL(url).search);<br>const obj = Object.fromEntries(params);<br>console.log(obj); // { name: 'John', age: '30' }<br>
动态创建对象 当键名需要在运行时动态生成时。 javascript<br>const keys = ['firstName', 'lastName'];<br>const values = ['Alice', 'Smith'];<br>const entries = keys.map((key, index) => [key, values[index]]);<br>const obj = Object.fromEntries(entries);<br>console.log(obj); // { firstName: 'Alice', lastName: 'Smith' }<br>
数据转换 从某种格式的数据转换成对象格式。例如,从 CSV 数据转换成对象数组,或者从数据库查询结果转换成对象。 javascript<br>// 假设 csvData 是一个 CSV 格式的字符串<br>const csvData = `name,age\nBob,25\nAlice,30`;<br>const lines = csvData.split('\n');<br>const headers = lines[0].split(',');<br>const data = lines.slice(1).map(line => {<br> const values = line.split(',');<br> const entries = headers.map((header, index) => [header, values[index]]);<br> return Object.fromEntries(entries);<br>});<br>console.log(data); // [{ name: 'Bob', age: '25' }, { name: 'Alice', age: '30' }]<br>
配置对象合并 当需要将多个配置对象合并成一个,并且配置对象是以键值对数组的形式存在时。 javascript<br>const config1 = [['theme', 'dark'], ['language', 'en']];<br>const config2 = [['fontSize', '16px'], ['theme', 'light']]; // 后面的 theme 会覆盖前面的<br>const mergedConfig = Object.fromEntries([...config1, ...config2]);<br>console.log(mergedConfig); // { theme: 'light', language: 'en', fontSize: '16px' }<br>

总结

Object.fromEntries() 是一个简洁、实用且语义化的 JavaScript 方法,用于将 Map 对象或键值对数组转换为普通对象。它可以简化代码,提高可读性,并在处理 URL 查询字符串、动态创建对象等场景中发挥重要作用。 虽然它有一些需要注意的地方,例如重复键的处理和键的类型转换,但只要我们了解了这些特性,就可以充分利用 Object.fromEntries() 的优势,让我们的代码更加优雅。

希望今天的讲解能帮助大家更好地理解和使用 Object.fromEntries()。下次再遇到需要将 Map 或键值对数组转换为对象的情况,记得用它来“变个魔术”哦!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注