在js开发中,处理对象数组时经常会遇到部分对象缺少必要字段的情况,这时候需要为这些缺失的字段添加默认值。不少开发者会想到使用defaults相关的能力来完成这个需求,下面我们就来详细讲解具体的实现方式。

原生js手动实现defaults逻辑
如果不想依赖第三方库,我们可以自己实现类似defaults的逻辑,遍历对象数组的每个元素,判断对应字段是否存在,不存在就赋值默认值。核心思路是先定义好默认配置对象,然后遍历数组中的每个对象,将默认配置和原对象合并,原对象已有的字段会覆盖默认值。
下面是一个简单的实现示例:
// 定义默认值对象
const defaultObj = {
name: '未知用户',
age: 0,
gender: '未设置'
};
// 原始对象数组,部分元素缺少字段
const userList = [
{ name: '张三', age: 20 },
{ name: '李四' },
{ age: 25, gender: '男' },
{}
];
// 手动实现defaults逻辑,为数组每个对象添加默认值
function applyDefaultsToArray(arr, defaults) {
return arr.map(item => {
// 遍历默认值的所有键
const result = { ...item };
Object.keys(defaults).forEach(key => {
// 如果原对象没有该键或者值为undefined,就使用默认值
if (result[key] === undefined) {
result[key] = defaults[key];
}
});
return result;
});
}
const newUserList = applyDefaultsToArray(userList, defaultObj);
console.log(newUserList);
上面的代码中,applyDefaultsToArray函数接收对象数组和默认值对象,通过map遍历数组,对每个对象检查默认值中的字段是否存在,不存在就补充默认值,最终返回处理后的新数组,不会修改原数组。
使用lodash的defaults方法实现
如果项目中已经引入了lodash工具库,可以直接使用lodash提供的_.defaults方法,这个方法的作用就是为对象填充默认值,原对象已有的属性不会被覆盖。我们需要遍历对象数组,对每个元素调用_.defaults即可。
首先确保已经引入lodash,然后看下面的示例:
// 假设已经引入lodash,全局有_对象
const _ = require('lodash');
// 同样的默认值对象和原始数组
const defaultObj = {
name: '未知用户',
age: 0,
gender: '未设置'
};
const userList = [
{ name: '张三', age: 20 },
{ name: '李四' },
{ age: 25, gender: '男' },
{}
];
// 使用lodash的defaults处理对象数组
const newUserList = userList.map(user => _.defaults({}, user, defaultObj));
console.log(newUserList);
这里需要注意,_.defaults会修改第一个参数对象,所以我们传入一个空对象作为第一个参数,第二个参数是原对象,第三个是默认值,这样就不会修改原数组中的对象,返回的新数组每个元素都补充了缺失的默认值。
处理嵌套对象的默认值
如果对象数组中的元素包含嵌套对象,上面的简单方法就无法处理嵌套字段的默认值了,这时候需要递归处理对象的每一层。我们可以扩展之前的手动实现方法,支持嵌套对象的默认值填充。
示例代码如下:
// 带嵌套结构的默认值
const defaultObj = {
name: '未知用户',
age: 0,
address: {
city: '未知城市',
street: '未知街道'
}
};
// 带嵌套结构的原始数组
const userList = [
{ name: '张三', address: { city: '北京' } },
{ age: 25 },
{ address: { street: '长安街' } }
];
// 递归处理嵌套对象的defaults逻辑
function deepApplyDefaults(target, defaults) {
const result = { ...target };
Object.keys(defaults).forEach(key => {
if (defaults[key] !== null && typeof defaults[key] === 'object' && !Array.isArray(defaults[key])) {
// 如果默认值是对象,递归处理
result[key] = deepApplyDefaults(result[key] || {}, defaults[key]);
} else if (result[key] === undefined) {
// 非对象类型,缺失就赋值默认值
result[key] = defaults[key];
}
});
return result;
}
const newUserList = userList.map(user => deepApplyDefaults(user, defaultObj));
console.log(newUserList);
这个递归方法会逐层检查对象的字段,如果默认值是普通对象,就对原对象对应的字段也做递归处理,这样就能正确填充嵌套结构的默认值了。
注意事项
- 处理对象数组时,尽量不要直接修改原数组,建议返回新的数组和对象,避免产生副作用。
- 如果默认值中包含引用类型(比如对象、数组),要注意避免多个对象共享同一个引用类型的默认值,上面的递归方法中每次都创建新对象,已经避免了这个问题。
- 使用第三方库的defaults方法时,要确认方法的参数顺序和是否修改原对象,避免不符合预期的行为。
实际开发中可以根据项目依赖和场景选择合适的实现方式,原生实现更轻量,第三方库方法更简洁,嵌套场景需要额外做递归处理。