请求解析JavaScript中扩展语法与赋值的易出错细节及注意事项
JavaScript 对象扩展语法
{...b} 的陷阱与注意事项 你已经清楚直接对象赋值是引用共享,而扩展语法 {...b} 本质是浅拷贝,这正是它最容易踩坑的核心原因,具体陷阱和注意事项如下:
1. 嵌套对象仍为引用共享
扩展语法只会拷贝对象的第一层属性,嵌套的子对象依然是原对象的引用,修改子对象会同步影响原对象:
const b = { basic: 'foo', nested: { key: 'bar' } }; const c = {...b}; c.nested.key = 'changed'; console.log(b.nested.key); // 输出 "changed"
2. 无法继承原型链属性
如果原对象是某个构造函数的实例,扩展语法只会拷贝对象自身的可枚举属性,原型链上的方法和属性不会被复制:
function User(name) { this.name = name; } User.prototype.sayHi = function() { console.log(`Hi, ${this.name}`); }; const b = new User('Jack'); const c = {...b}; c.sayHi(); // 报错:c.sayHi is not a function
3. 特殊内置对象类型丢失
对于 Date、RegExp、Map、Set 这类内置对象,扩展语法只会拷贝它们的可枚举属性,无法生成同类型的实例,导致对象特性丢失:
const b = new Date('2024-05-20'); const c = {...b}; console.log(c instanceof Date); // 输出 false console.log(typeof c); // 输出 "object"(普通对象)
4. 不可枚举属性被忽略
扩展语法仅拷贝对象的可枚举属性,通过 Object.defineProperty 定义的不可枚举属性不会被复制:
const b = {}; Object.defineProperty(b, 'hidden', { value: 'secret', enumerable: false }); const c = {...b}; console.log(c.hidden); // 输出 undefined
注意事项
- 若需深拷贝嵌套对象:可以手动逐层拷贝,或使用
JSON.parse(JSON.stringify(b))(但该方法无法处理函数、undefined、循环引用),也可以用成熟的深拷贝工具函数。 - 保留原型链的拷贝方式:如果需要继承原对象的原型,可以使用
Object.create(Object.getPrototypeOf(b), Object.getOwnPropertyDescriptors(b))。 - 特殊对象的针对性拷贝:处理 Date 用
new Date(b),RegExp 用new RegExp(b.source, b.flags),Map/Set 则可以通过构造函数重新实例化。
内容的提问来源于stack exchange,提问作者Octo Palm Tree
相关产品推荐
相关产品推荐

