DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

JavaScript 已给解构参数默认值,传 null 仍报 TypeError

解构参数的外层默认值只处理省略参数或 undefined。根据接口是否允许 null,选择修正调用方或在函数体内先归一化,再分别验证属性默认值。

函数参数已经写了 = {},传入 null 却在进入函数体之前抛出 TypeError:

function displayName({ name = "anonymous" } = {}) {
  return name;
}

displayName(null);

错误可能包含 Cannot destructure property,具体文字随运行环境变化。这里针对支持 ES2015 解构和默认参数的 JavaScript 环境。

外层默认值只接住 undefined

这段声明有两层默认值。外面的 = {} 在参数省略或为 undefined 时生效;里面的 name = "anonymous" 在对象的 name 属性值为 undefined 时生效。传入 null 不会触发外层默认值,而 null 不能作为对象解构,所以还没有机会读取 name。

以下调用能区分这两层规则:

displayName();                  // 预期 "anonymous"
displayName(undefined);         // 预期 "anonymous"
displayName({});                // 预期 "anonymous"
displayName({ name: null });    // 预期 null

把参数改写成 function displayName(options = {}),随后直接解构 options,仍然不能处理显式传来的 null。默认值的触发条件没有改变。

允许 null 表示缺省时,先归一化再解构

如果接口明确把 null 与未传参数都视为“没有选项”,把解构移到函数体内:

function displayName(options) {
  const actual = options === null || options === undefined ? {} : options;
  const { name = "anonymous" } = actual;
  return name;
}

displayName(null);              // 预期 "anonymous"
displayName(undefined);         // 预期 "anonymous"
displayName({ name: "Lin" });   // 预期 "Lin"
displayName({ name: "" });      // 预期 ""
displayName({ name: null });    // 预期 null

这里仅归一化整个参数的空值,并没有把对象内部的 name: null 替换掉。如果属性里的 null 也应使用默认名称,需要另行明确这个字段的规则,不能以为外层修复已经覆盖所有层级。

options || {} 会把其他假值也替换掉。为了清楚表达“只处理 null 与 undefined”,示例使用显式判断。它仍不是完整的输入校验:数字、字符串、数组等是否可接受,必须由接口约定决定,不能把“解构没有报错”当成合法对象的证明。

null 本来表示错误时,应修复调用方

有些查询用 null 表示没有找到记录,调用方本应走缺失分支。这时把它变成空对象,可能只是把原来的异常换成错误的默认名称。应检查传参位置,确认空值从哪里产生,再决定是提前返回、报告缺失,还是允许缺省选项。

修改后分别覆盖省略参数、undefined、null、空对象、正常名称和显式空字符串,检查结果符合接口约定。若有嵌套解构,还需对嵌套对象的空值单独判断。

保留原函数与调用方版本。回退“接受 null”的改动会恢复原来的异常行为,依赖新规则的调用方也要同步核对;不要在外层捕获所有 TypeError 并统一返回默认值,那会把函数内部其他错误一并隐藏。