对象扁平化
将嵌套的对象结构转换为扁平的键值对形式,使用点号连接嵌套的键名
问题
对象扁平化是指将一个多层嵌套的对象转换为单层对象,其中嵌套的键通过特定分隔符(通常是点号)连接起来。例如:
// 输入
{
a: 1,
b: {
c: 2,
d: {
e: 3
}
}
}
// 输出
{
'a': 1,
'b.c': 2,
'b.d.e': 3
}
这在处理表单数据、配置文件或需要将复杂对象结构转换为简单键值对时非常有用。
解答
/**
* 对象扁平化
* @param {Object} obj - 需要扁平化的对象
* @param {string} prefix - 键名前缀
* @param {Object} result - 结果对象
* @returns {Object} 扁平化后的对象
*/
function flattenObject(obj, prefix = '', result = {}) {
// 遍历对象的所有键
for (let key in obj) {
// 只处理对象自身的属性
if (obj.hasOwnProperty(key)) {
// 构造新的键名
const newKey = prefix ? `${prefix}.${key}` : key;
// 判断值的类型
if (obj[key] !== null && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
// 如果是对象(非数组、非null),递归处理
flattenObject(obj[key], newKey, result);
} else {
// 如果是基本类型或数组,直接赋值
result[newKey] = obj[key];
}
}
}
return result;
}
// 方法二:使用迭代方式实现
function flattenObjectIterative(obj) {
const result = {};
const stack = [{ value: obj, prefix: '' }];
while (stack.length > 0) {
const { value, prefix } = stack.pop();
for (let key in value) {
if (value.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value[key] !== null && typeof value[key] === 'object' && !Array.isArray(value[key])) {
// 将嵌套对象压入栈中
stack.push({ value: value[key], prefix: newKey });
} else {
result[newKey] = value[key];
}
}
}
}
return result;
}
使用示例
// 示例1:基本嵌套对象
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 3
}
}
};
console.log(flattenObject(obj1));
// 输出: { a: 1, 'b.c': 2, 'b.d.e': 3 }
// 示例2:包含数组的对象
const obj2 = {
name: 'John',
info: {
age: 30,
hobbies: ['reading', 'coding'],
address: {
city: 'Beijing',
street: 'Main St'
}
}
};
console.log(flattenObject(obj2));
// 输出: {
// name: 'John',
// 'info.age': 30,
// 'info.hobbies': ['reading', 'coding'],
// 'info.address.city': 'Beijing',
// 'info.address.street': 'Main St'
// }
// 示例3:包含null和undefined
const obj3 = {
a: null,
b: undefined,
c: {
d: null,
e: 0,
f: false
}
};
console.log(flattenObject(obj3));
// 输出: {
// a: null,
// b: undefined,
// 'c.d': null,
// 'c.e': 0,
// 'c.f': false
// }
// 示例4:空对象
const obj4 = {
a: 1,
b: {},
c: {
d: 2
}
};
console.log(flattenObject(obj4));
// 输出: { a: 1, 'c.d': 2 }
关键点
-
递归遍历:使用递归方式遍历对象的每一层,将嵌套结构展开
-
类型判断:需要准确判断值的类型,区分对象、数组、null 和基本类型
- 使用
typeof obj[key] === 'object'判断是否为对象类型 - 使用
Array.isArray()排除数组 - 使用
!== null排除 null(因为 typeof null 也是 ‘object’)
- 使用
-
键名拼接:使用点号(
.)连接父级键名和当前键名,形成完整路径 -
边界处理:
- 空对象不会产生键值对
- 数组作为值直接保留,不进行展开
- null、undefined 等特殊值需要正确处理
-
性能优化:对于深层嵌套的大对象,可以考虑使用迭代方式代替递归,避免栈溢出
-
扩展性:可以根据需求自定义分隔符、处理数组的方式等
目录