You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript扩展运算符保留设为undefined的键?与未定义键有何区别?

JavaScript中显式赋值为undefined的属性与未定义属性的差异

在JavaScript里,对象中显式赋值为undefined的属性和从未定义过的属性常被开发者混淆——毕竟访问二者时typeof结果都是undefined,而且JSON.stringify都会忽略它们,但这两者本质上完全不同,最直观的差异就体现在扩展运算符的行为上。

核心本质区别

  • 显式赋值为undefined的属性:属于对象的可枚举自有属性,实实在在存在于对象的属性集合中,只是值为undefined。
  • 未定义的属性:完全不存在于对象中,访问时返回undefined仅仅是JavaScript的默认行为,该属性从未被添加到对象里。

代码示例分析

先看你提供的代码运行结果(补充注释):

const obj1 = {a: "apple", c:"crab", d:"dagger", e: undefined};
const obj2 = {a: "aardvark", b:"blue", c: undefined, f: "flamethrower", g: undefined};

const res1 = {
  ...obj1,
  ...obj2
};
// res1结果:{a: "aardvark", c: undefined, d: "dagger", e: undefined, b: "blue", f: "flamethrower", g: undefined}
// 原因:扩展运算符遍历对象所有可枚举自有属性,obj2的c: undefined覆盖obj1的c: "crab",同时obj2的b、f、g(含值为undefined的g)都被合并

const res2 = {
  ...obj2,
  ...obj1
};
// res2结果:{a: "apple", b: "blue", c: "crab", f: "flamethrower", g: undefined, d: "dagger", e: undefined}
// 原因:obj1的c: "crab"覆盖obj2的c: undefined,obj1的d、e(值为undefined)被合并进来

const res3 = {
  ...obj1
};
// res3结果:{a: "apple", c: "crab", d: "dagger", e: undefined}
// 原因:obj1的e是显式定义的属性,扩展运算符会保留它;h从未定义,所以res3中没有h属性

console.log(res1);
console.log('====');
console.log(res2);
console.log('====');
console.log(res3);
console.log('====');
console.log(typeof res3.e); // undefined(属性存在,值为undefined)
console.log(typeof res3.h); // undefined(属性不存在,访问返回默认undefined)
console.log(JSON.stringify(obj1)); // {"a":"apple","c":"crab","d":"dagger"}(JSON.stringify忽略值为undefined的属性)

其他场景的差异表现

除了扩展运算符,这两种属性在很多API中的行为都不一样:

  • 对象遍历:for...in、Object.keys()、Object.getOwnPropertyNames()都会遍历到显式赋值为undefined的属性,但不会处理未定义的属性。
  • 属性存在性检查:obj.hasOwnProperty('e')对显式undefined的属性返回true,对未定义的属性返回false。
  • 解构赋值:解构显式undefined的属性会得到undefined;解构未定义的属性时,如果设置了默认值,会使用默认值,否则才返回undefined:
    const { e = 'default', h = 'default' } = obj1;
    console.log(e); // undefined(属性存在,值为undefined)
    console.log(h); // 'default'(属性不存在,使用默认值)
    
  • Object.assign():和扩展运算符逻辑一致,会复制显式undefined的属性,不会处理未定义的属性。

总结

别再把“显式设置属性值为undefined”和“未定义属性”混为一谈——前者是存在但值为undefined,后者是根本不存在。不同的JavaScript API会根据这个本质差异做出不同处理,记住这一点就能避免很多类似的坑。

内容的提问来源于stack exchange,提问作者Summitch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:16:22