JS/TS中Object.assign、new构造函数与直接重赋值操作类实例的区别
三种克隆/重赋值方案的本质差异
方案1:Object.assign 浅拷贝
const nextMiddle = Object.assign({}, highestInstance.middle) nextMiddle.lowest.someValue = "some other thing" highestInstance.middle = nextMiddle
- 本质:生成的是普通JS对象,而非Middle类的实例,仅将原Middle实例的可枚举自有属性浅拷贝到空对象上。
- 异常原因:
- 新对象的原型指向
Object.prototype而非Middle.prototype,如果Middle类定义了原型方法,新对象调用时会直接报错。 - 浅拷贝仅复制
lowest属性的引用,修改nextMiddle.lowest.someValue时实际修改的还是原Middle实例绑定的Lowest对象。 - 若
otherValue.doSomething要求入参是合法的Middle实例,传入普通对象会触发类型错误。
- 新对象的原型指向
方案2:原实例引用重赋值
const nextMiddle = highestInstance.middle nextMiddle.lowest.someValue = "some other thing" highestInstance.middle = nextMiddle
- 本质:没有做任何克隆,
nextMiddle和Highest内部持有的_middle是完全相同的引用,仅触发了setter的执行逻辑。 - 行为说明:
- 修改
nextMiddle.lowest.someValue就是直接修改原Middle实例的内部属性,其实违反了你最初「不能直接修改Highest.middle.lowest值」的规则,只是额外触发了otherValue.doSomething的更新逻辑,刚好满足了你的业务要求。 - 如果项目其他逻辑依赖Middle实例的不可变性,该方案会产生隐性副作用。
- 修改
方案3:copy方法生成全新实例
- 本质:创建了完全独立的Middle类实例,连带也生成了新的Lowest类实例,新旧实例没有任何共享的引用对象。
- 优势:
- 是合法的Middle类实例,原型链、类方法都完整,不会出现方案1的类型异常。
- 修改新实例属性不会影响旧实例,符合不可变数据修改规范,不会产生隐性副作用。
- 赋值时既触发了setter的更新逻辑,也真正替换了Highest持有的Middle实例,完全符合架构设计要求。
内容的提问来源于stack exchange,提问作者foxtrotuniform6969
相关产品推荐
相关产品推荐

