迁移到原生 Object.groupBy 可简化代码,但需注意浏览器兼容性(Chrome 117+)及返回值是无原型对象,无法直接使用 hasOwnProperty 等方法。
先说结论:适合现代浏览器和 Node.js 环境,重点看返回值原型链差异,别忽略键值类型强制转换。
- 适合:Chrome 117+ 或支持 ES2024 的运行环境
- 重点看:返回对象无原型,不能调用 Object.prototype 方法
- 别忽略:回调返回的非字符串键会被强制转换为字符串
快速处理思路
迁移工作主要分为环境检测、语法替换和原型方法修复三步。
1. 检测运行环境是否支持 Object.groupBy,旧环境需保留 polyfill 或继续使用 Lodash。
2. 将 _.groupBy(data, iteratee) 替换为 Object.groupBy(data, iteratee)。
3. 检查代码中是否对分组结果调用了 hasOwnProperty、toString 等原型方法,改为 Object.hasOwn 或 typeof 检查。
为什么会这样
原生 Object.groupBy 返回的是无原型对象,旨在避免原型污染但限制了对象方法调用。
该方法是 ES2024 新特性,设计上当返回一个没有原型(即没有继承任何属性和方法)的对象,这意味着该对象不会继承 Object.prototype 上的任何属性或方法,例如 hasOwnProperty 或 toString 等,虽然这样做可以避免意外覆盖 Object.prototype 上的属性,但也意味着不能使用一些与对象相关的方法。
分步处理
按步骤执行迁移,每步完成后需检查代码逻辑是否受影响。
步骤 1:环境兼容性检查
确认目标用户浏览器版本,Chrome 117 已经支持了这两个方法,低于此版本需引入 polyfill 或降级处理。
步骤 2:语法替换
将 Lodash 的 groupBy 调用替换为原生静态方法,语法为 Object.groupBy(items, callbackFn),其中 callbackFn 返回的值用作分组的键。
步骤 3:原型方法修复
搜索代码中针对分组结果对象的 hasOwnProperty 调用,替换为 Object.hasOwn(groupResult, key) 或 key in groupResult 判断。
怎么验证是否生效
通过控制台检查返回对象的原型链及方法可用性来验证。
在浏览器控制台执行分组代码后,输入 Object.getPrototypeOf(result) 应返回 null。
尝试执行 result.hasOwnProperty('key') 应抛出 TypeError 或返回 undefined,而 Object.hasOwn(result, 'key') 应正常返回布尔值。
常见坑
迁移过程中容易忽略键值类型转换和旧环境兼容性问题。
1. 键值类型强制转换
在调用 Object.groupBy 时,传递给它的回调函数应该返回一个字符串或 Symbol 类型的值,如果回调函数返回其他类型的值,它将被强制转换为字符串,例如数字类型的 age 属性值会被强制转换为字符串类型。
2. 原型方法不可用
返回的对象没有原型,直接使用 result.toString() 或 result.valueOf() 会报错,需改用 Object.prototype.toString.call(result)。
3. 旧环境报错
在不支持 ES2024 的环境中直接调用会抛出 undefined is not a function 错误,需配合构建工具进行转译或条件加载。
常见问题
Object.groupBy 支持哪些浏览器?
目前最新版本的 Chrome(117) 已经支持了这两个方法,其他浏览器需查询兼容性表。
迁移后还能用 Lodash 的其他方法吗?
可以,Lodash 提供了大量简化复杂逻辑的工具函数,例如深层克隆、对象深比较等操作若用原生实现需要编写大量代码。
Map.groupBy 和 Object.groupBy 有什么区别?
如果你需要使用任意值(不仅仅是字符串)来进行分组,Map.groupBy 函数也能帮你搞定,它允许更灵活的键类型。
参考来源
- JavaScript 终于原生支持数组分组了!
- 叒震惊?!ES15 (2024) 5 个全新 JavaScript 特性
- Lodash 的又一方法被替代了,探索 JS 新特性 Object.groupBy
- ES2024 新特性:object.groupBy() 让分组更简单
- 在实际应用中,如何选择使用原生 JavaScript 还是 Lodash 来进行数组操作?