浅拷贝不会导致属性丢失,而是只复制自有可枚举属性,跳过不可枚举属性、原型链属性、symbol键(展开运算符)等;getter/setter可能被扁平化,数组自定义属性丢失,本质是严格按规范筛选而非删除。

浅拷贝本身不会“导致”属性丢失,但会因机制限制而漏掉某些本应存在的属性。关键不是它删了什么,而是它只复制了哪些——理解这个边界,才能避免误用。
只复制自有可枚举属性
Object.assign() 和展开运算符({...obj})默认只遍历并复制对象自身的、可枚举的属性。以下几类属性会被跳过:
- 不可枚举属性(如通过
Object.defineProperty设置enumerable: false的属性) - 原型链上的属性(比如定义在
obj.__proto__或构造函数prototype上的方法或字段) - Symbol 类型的键名属性(即使可枚举,展开运算符也不处理;
Object.assign能复制 Symbol 键,但需明确传入)
原型链属性不继承,等于“消失”
如果原对象的方法或数据来自原型(例如自定义构造函数的原型方法,或扩展了 Object.prototype),浅拷贝后的新对象将失去这些能力:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const obj = Object.create({ sayHi() { return 'hi'; } }); obj.name = 'Alice';-
const copy = { ...obj };→copy.sayHi是undefined,因为sayHi在原型上,没被复制 - 若需保留,必须手动重建原型关系:
Object.assign(Object.create(Object.getPrototypeOf(obj)), obj)
getter/setter 和不可配置属性容易被“扁平化”
浅拷贝对访问器属性(getter/setter)的处理不透明:
- 如果原对象某个属性是 getter,且
configurable: true,Object.assign会把它变成一个普通数据属性(即执行一次 getter,存结果) - 如果
configurable: false,复制仍能成功,但新对象上该属性无法被删除或重定义 - 原型上的 getter/setter 不会被复制,只能靠继承——前提是新对象的原型正确设置
数组与类数组对象的特殊表现
数组用展开语法或 slice() 浅拷贝时,会丢失自定义属性:
-
const arr = [1, 2]; arr.custom = 'meta'; const copy = [...arr];→copy.custom是undefined - 这是因为数组的自有属性(非索引项)通常不可枚举,且
Array.prototype方法不遍历它们 - 若需保留,得显式复制:
Object.assign([...arr], { custom: arr.custom })
本质上,浅拷贝不是“丢属性”,而是按规范严格筛选——它只做它承诺的事:一层自有可枚举属性的搬运工。真正的问题,往往出在预期和行为不匹配。明确你要保留什么,再选对应策略,比事后排查“为什么没了”更高效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










