ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 `map` 与箭头函数将对象数组映射为对象数组:括号陷阱与实战详解(现代 JavaScript 教程 7-map-objects 题解)

用 `map` 与箭头函数将对象数组映射为对象数组:括号陷阱与实战详解(现代 JavaScript 教程 7-map-objects 题解) 文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载本篇基于《现代 JavaScript 教程》zh.javascript.info数组方法章节中的习题映射到对象7-map-objects及其官方题解完整还原题目、解答思路与语法细节并深入讲解Array.prototype.map与箭头函数组合使用时最经典的返回对象必须加括号陷阱。读完本文你将能够独立完成对象数组 → 新结构对象数组的数据重塑并理解其背后的 JavaScript 语法解析原理。题目回顾把一组用户对象映射为fullName id结构在数组方法章节的习题7-map-objects中我们拿到了一个由三个用户对象组成的数组每个对象包含name、surname和id三个字段let john { name: John, surname: Smith, id: 1 }; let pete { name: Pete, surname: Hunt, id: 2 }; let mary { name: Mary, surname: Key, id: 3 }; let users [ john, pete, mary ];任务要求以该数组为基础创建一个新的对象数组usersMapped其中的每个元素只有两个字段id—— 沿用原对象的idfullName—— 由name和surname拼接而成。期望结果如下/* usersMapped [ { fullName: John Smith, id: 1 }, { fullName: Pete Hunt, id: 2 }, { fullName: Mary Key, id: 3 } ] */ alert( usersMapped[0].id ); // 1 alert( usersMapped[0].fullName ); // John Smith这是一个典型的将一个对象数组映射到另一个对象数组的场景源数据的字段布局与目标数据的字段布局不一致需要借助map完成结构转换。题目特别提示使用箭头函数来编写这正是为了引出本文的核心知识点——箭头函数返回对象字面量时的括号语法。标准解答users.map(user ({ ... }))官方题解给出的完整代码如下let john { name: John, surname: Smith, id: 1 }; let pete { name: Pete, surname: Hunt, id: 2 }; let mary { name: Mary, surname: Key, id: 3 }; let users [ john, pete, mary ]; let usersMapped users.map(user ({ fullName: ${user.name} ${user.surname}, id: user.id })); alert( usersMapped[0].id ); // 1 alert( usersMapped[0].fullName ); // John Smith逐行拆解这段代码users.map(...)—— 对users数组的每个元素调用一次回调函数并把每次调用的返回值收集成一个新数组原数组users保持不变map是非破坏性的这一点与sort、reverse、splice等原位修改方法截然不同可对照数组方法章节的总结查看备忘单。user ({ ... })—— 箭头函数接收当前元素user返回一个新建的对象字面量。fullName: ${user.name} ${user.surname}—— 使用模板字符串template literal把name与surname用空格拼接得到John Smith这样的全名。id: user.id—— 原样拷贝id字段。执行后usersMapped的元素顺序与原数组一一对应即完成了{ name, surname, id }→{ fullName, id }的结构重塑。核心陷阱箭头函数返回对象时{会被当成函数体题解中特别强调请注意在箭头函数中我们需要使用额外的括号。这样写是错误的let usersMapped users.map(user { fullName: ${user.name} ${user.surname}, id: user.id });必须这样写let usersMapped users.map(user ({ fullName: ${user.name} ${user.surname}, id: user.id }));为什么这涉及箭头函数的两种形态。正如箭头函数基础章节所总结的不带花括号(...args) expression—— 右侧是一个表达式函数直接计算并返回该表达式的结果带花括号(...args) { body }—— 花括号表示多行函数体此时必须显式使用return才能返回值。当我们写user { fullName: ..., id: ... }时JavaScript 解析器把这里的{视为函数体的开始而不是对象字面量的开始。于是fullName: ...会被解析成一个带标签label的语句id: ...同理整个箭头函数体执行完毕后没有任何return最终返回undefined——每个元素都被映射成了undefined。解决方法把对象字面量整体包装在普通括号()中即user ({ ... })。括号改变了解析优先级让{明确成为对象字面量的起始符号同时箭头函数又回归expression直接返回的形态无需写return。官方题解中的这样就可以了指的就是这一行改动。补充说明如果改用带函数体的写法则显式return也是完全可行的例如user { return { fullName: ..., id: ... }; }。只是利用表达式直接返回形态加括号的写法更简洁也更常见。为什么map特别适合这种数据重塑任务map是数组方法中最有用和经常使用的方法之一官方教程对其语法定义如下let result arr.map(function(item, index, array) { // 返回新值而不是当前元素 })回调函数接收三个参数item当前元素、index索引、array数组本身map对每个元素调用该函数并以返回值构建新数组。正是每个元素 → 返回一个新值的语义让它成为对象数组结构转换的首选工具。本章中的另一道习题6-array-get-names展示了它的最简形态——只提取单字段let names users.map(item item.name); // John, Pete, Mary而本题则是它的进阶形态——返回一个由多个字段重新组合而成的新对象。两者对比可以清晰看出map的回调返回值既可以是基本类型也可以是对象灵活性极高。在真实项目中这类映射为对象的写法极为常见典型场景包括后端接口返回的扁平数据映射为前端视图模型如把name surname拼成展示用的fullName或把userId重命名为id以对接组件 props为列表项附加计算字段如price * quantity得到total数据脱敏或字段裁剪只保留指定字段丢弃多余字段。结合深入理解箭头函数章节的知识点这里使用箭头函数还有一层额外收益箭头函数没有自己的this其中的this会从外部词法环境查找。因此当map的回调需要访问外层上下文例如外层对象的属性、外层this指向的数据源时箭头函数不会像普通函数那样丢失this也不必额外.bind(this)。延伸字段名相同时的简写与更多变体如果目标对象的字段名与源对象一致例如只需要拷贝id可以借助对象属性简写shorthand property让代码更紧凑let usersMapped users.map(user ({ id: user.id, // 字段名与变量同名时可写作 id, fullName: ${user.name} ${user.surname} }));更地道的做法是先在函数体内解构出所需字段再组合新对象let usersMapped users.map(({ name, surname, id }) ({ fullName: ${name} ${surname}, id }));这里用到了函数参数解构map传入的每个user对象在进入回调时被直接拆解为name、surname、id三个局部变量配合属性简写id语义一目了然。这也是对象数组 → 对象数组映射在实际工程中非常流行的写法。若映射逻辑较复杂多行语句则可退回到带函数体的箭头函数形式let usersMapped users.map(user { const fullName ${user.name} ${user.surname}; return { fullName, id: user.id }; });注意此时必须写显式return——这恰好与上一节{即函数体的解析规则互为印证一旦{被解析为函数体返回值就只能靠return给出。与相关数组方法的横向对比理解本题的map之后可以把它放进数组方法章节的完整图谱中定位方法返回内容与本题的关系map(fn)与源数组等长的新数组元素为每个回调返回值本题的核心工具一对一转换filter(fn)新数组仅包含回调返回真值的元素一对多中筛选与map常组合成先过滤后映射管道forEach(fn)undefined仅遍历副作用只遍历不产出新数组无法替代本题需求reduce(fn, initial)单个聚合值若需要映射 汇总为单个结果可在此之上叠加举例来说若需求变为只保留id为偶数的用户并生成fullName典型写法就是管道式组合let usersMapped users .filter(user user.id % 2 0) .map(user ({ fullName: ${user.name} ${user.surname}, id: user.id }));filter的语法与find大致相同但返回所有匹配项组成的数组二者语义上的分工详见数组方法章节的 filter 小节。易错点自查清单括号不可省箭头函数返回对象字面量时必须写user ({ ... })否则{被当作函数体返回undefinedmap不改原数组users保持原样新结构存放于usersMapped需要副本而非原地修改时优先map模板字符串拼接${user.name} ${user.surname}中间的空格是fullName可读性的关键勿漏字段名简写id: user.id在解构后可简写为id提升可读性函数体形态需显式return一旦写成user { ... }返回值必须由return给出两种形态不可混用。总结映射到对象是一道将map、箭头函数、对象字面量与模板字符串四个知识点融于一炉的经典习题。其标准解法的灵魂在于一行括号users.map(user ({ fullName: ..., id: ... }))。理解箭头函数的{优先被解析为函数体这一语法规则不仅能解对这道题更能避免在实际项目中写出映射出全undefined数组的隐性 bug。掌握本文的写法与变体解构、简写、与filter组合你就能熟练完成绝大多数对象数组重塑需求更多数组方法sort、reduce、flatMap等的完整清单可继续研读数组方法章节并在该章节的系列习题中反复演练。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐JavaScript 对象数组映射用 map 与箭头函数生成 fullName 的完整指南JavaScript 对象数组映射用 map 与箭头函数生成 fullName 的完整指南 在 Modern JavaScript Tutorial http文档/教程前端JavaScript 数组 map 方法实战将对象数组映射为 name 数组zh.javascript.info 习题精解JavaScript 数组 map 方法实战将对象数组映射为 name 数组zh.javascript.info 习题精解 导读 本文以《现代 JavaS文档教程前端Modern JavaScript Tutorial 实战用 Array.map 将用户对象数组映射为姓名数组Map to namesModern JavaScript Tutorial 实战用 Array.map 将用户对象数组映射为姓名数组Map to names 导读 本篇基于 M文档/教程前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表