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 并统一返回默认值,那会把函数内部其他错误一并隐藏。


