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或{}作为参数,函数均应返回默认值而不报错。

对象属性访问错误修复流程 修复前: user.profile.firstName user.profile 为 undefined TypeError 抛出 修复后: user?.profile?.firstName ?? '未知' 可选链短路,返回 undefined 空值合并提供默认值: "未知 用户" 验证判定标准 1. 执行 node fix.js 不抛出任何异常 2. 第一行输出 "未知 用户",第二行输出 "20"