4. 修复对象属性访问错误
任务说明
在JavaScript中,访问不存在或未初始化的对象属性会返回undefined,若随后对该值进行方法调用或属性访问,将抛出TypeError: Cannot read properties of undefined。本案例要求修复一段包含此类缺陷的代码,使其在给定输入下正确输出用户全名与订单金额,并给出可验证的修复前后对比。
缺陷代码
function getUserFullName(user) {
return user.profile.firstName + ' ' + user.profile.lastName;
}
function getOrderTotal(order) {
return order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// 调用示例
const user = { id: 1, name: 'Alice' }; // 缺少 profile 属性
const order = { id: 101, items: [{ price: 10, quantity: 2 }] };
console.log(getUserFullName(user)); // 抛出 TypeError
console.log(getOrderTotal(order)); // 正常输出 20
问题定位
缺陷集中在getUserFullName函数:它直接访问user.profile.firstName,但传入的user对象没有profile属性,导致访问undefined.firstName时抛出TypeError。修复策略是采用可选链(?.)与空值合并(??)进行防御性访问,并为缺失属性提供默认值。
修复后代码
function getUserFullName(user) {
const firstName = user?.profile?.firstName ?? '未知';
const lastName = user?.profile?.lastName ?? '用户';
return firstName + ' ' + lastName;
}
function getOrderTotal(order) {
// 同时防御 order 或 items 缺失的情况
if (!order?.items || !Array.isArray(order.items)) {
return 0;
}
return order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// 调用示例
const user = { id: 1, name: 'Alice' }; // 仍缺少 profile
const order = { id: 101, items: [{ price: 10, quantity: 2 }] };
console.log(getUserFullName(user)); // 预期输出: 未知 用户
console.log(getOrderTotal(order)); // 预期输出: 20
修复说明
修复后的getUserFullName使用user?.profile?.firstName进行链式安全访问:当user为null/undefined或profile不存在时,表达式短路返回undefined,随后由??提供默认值'未知'或'用户'。这样无论传入对象结构是否完整,函数都不会抛出异常。同时,getOrderTotal增加了对order和items的存在性检查,避免在数据缺失时崩溃。修复保持了原有正常路径的输出不变(订单金额仍为20),仅对异常路径增加了安全兜底。
验证方法
将修复后代码保存为fix.js,在Node.js环境中执行:
node fix.js
观察控制台输出:
- 第一行输出应为
未知 用户,证明访问缺失属性时不再抛出异常,而是返回默认值; - 第二行输出应为
20,证明正常数据路径的计算结果未受影响。
若两行输出与上述一致,则判定修复通过。可额外测试传入null或{}作为参数,函数均应返回默认值而不报错。