从对象数组中提取属性值作为数组
技术背景
在 JavaScript 开发中,我们经常会遇到从对象数组中提取某个属性值并将其转换为数组的需求。例如,从包含多个用户信息的对象数组中提取所有用户的姓名。这在数据处理、展示等场景中非常常见。
实现步骤
1. 使用 Array.prototype.map()
方法
map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
1 2 3
| let objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ]; let result = objArray.map(a => a.foo); console.log(result);
|
也可以使用对象解构:
1
| let result = objArray.map(({ foo }) => foo);
|
2. 使用传统 for
循环
1 2 3 4 5
| var vals = []; for(var i = 0; i < objArray.length; i++){ vals.push(objArray[i].foo); } console.log(vals);
|
3. 使用 for...of
循环
1 2 3 4 5
| var vals = []; for(var item of objArray){ vals.push(item.foo); } console.log(vals);
|
4. 使用 Lodash 或 Underscore 库
1 2 3
| const _ = require('lodash'); let result = _.map(objArray, "foo"); console.log(result);
|
1 2 3
| const _ = require('underscore'); let result = _.pluck(objArray, "foo"); console.log(result);
|
5. 使用 Array.from()
方法
如果要支持类数组对象或 Set
,可以使用 Array.from()
方法:
1 2 3
| let arrayLike = new Set([{foo: 1}, {foo: 2}, {foo: 3}]); let result = Array.from(arrayLike, x => x.foo); console.log(result);
|
核心代码
以下是一些核心代码示例:
提取单个属性
1 2 3 4 5 6 7 8 9 10
| function getFields(input, field) { return input.map(function(o) { return o[field]; }); }
let objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ]; let result = getFields(objArray, 'foo'); console.log(result);
|
提取多个属性
1 2 3 4 5 6 7 8
| let arrayOfObjects = [ {id:1, name:'one', desc:'something'}, {id:2, name:'two', desc:'something else'} ];
let result = arrayOfObjects.map(({id, name}) => ({id, name})); console.log(result);
|
最佳实践
- 性能方面:如果对性能要求较高,传统的
for
循环性能相对较好;如果追求代码的简洁性和可读性,map()
方法是不错的选择。 - 兼容性方面:如果需要兼容旧浏览器(如 IE8 及以下),则不能使用
map()
等 ES5 及以上的方法,可以考虑使用传统 for
循环或引入兼容库。 - 使用库方面:如果项目中已经使用了 Lodash 或 Underscore 库,可以使用它们提供的方法,这样可以减少代码量。
常见问题
1. map()
方法在旧浏览器中不支持
map()
是 ES5 的方法,在 IE8 及以下浏览器中不支持。可以引入 map()
的兼容代码或使用传统 for
循环。
2. 属性不存在时返回 undefined
使用 map()
方法时,如果对象中不存在指定的属性,会返回 undefined
。可以使用 reduce()
方法来处理这种情况:
1 2 3 4 5 6 7 8 9 10 11 12
| function getFields(list, field) { return list.reduce(function(carry, item) { if (typeof item === 'object' && field in item) { carry.push(item[field]); } return carry; }, []); }
let objArray = [ { foo: 1}, { }, { foo: 5} ]; let result = getFields(objArray, 'foo'); console.log(result);
|