Angular 5中两个不同对象间为何发生浅拷贝?
关于Angular服务对象引用与拷贝的问题解答
我来帮你逐个拆解这些问题,这都是JavaScript/TypeScript中对象引用模型的典型场景,很容易踩坑~
1. 第一种方案中为何会发生“浅拷贝”(本质是引用指向)?
其实严格来说,第一种方案不是浅拷贝,而是直接引用赋值。在JavaScript/TypeScript中,对象属于引用类型,它们的实际数据存储在堆内存中,变量本身只保存指向堆内存的地址。
看你的代码:
// serviceConsume.ts constructor( private gVar: GlobeVar ) { this.fVar = this.gVar.$fVar; }
GlobeVar服务的$fVar getter返回的是私有变量fVar的引用地址,当你把这个地址赋值给本地的fVar后,两个变量就指向了堆内存中的同一个对象。这时候你执行this.fVar.Step = null;,本质是修改了这个共享对象的属性,自然this.gVar.$fVar.Step也会同步变化——因为它们根本就是同一个对象。
2. 不使用Object.assign时,避免引用指向(实现浅拷贝)的最佳方式是什么?
如果不想让本地变量和服务里的对象共享引用,需要创建一个原对象的副本,以下是几种常用方案:
- ES6对象展开运算符:这是最简洁的浅拷贝方式,适合大多数简单对象场景
this.fVar = {...this.gVar.$fVar}; - 手动遍历赋值:如果需要对属性做额外处理,或者兼容旧环境,可以手动遍历原对象的属性:
this.fVar = {}; for (const key in this.gVar.$fVar) { if (this.gVar.$fVar.hasOwnProperty(key)) { this.fVar[key] = this.gVar.$fVar[key]; } } - JSON序列化反序列化:适合需要深拷贝的场景,但注意它有局限性(无法处理函数、undefined、循环引用、Symbol类型等):
this.fVar = JSON.parse(JSON.stringify(this.gVar.$fVar)); - 自定义类实例化:如果
$fVar是自定义类的实例,可以通过类的构造函数创建新实例:// 假设$fVar是MyClass的实例 this.fVar = new MyClass(this.gVar.$fVar);
3. 我的第二种方案是否正确?
你的第二种方案是正确的,Object.assign(this.fVar, this.gVar.$fVar)会把this.gVar.$fVar的所有可枚举属性复制到目标对象this.fVar(这里this.fVar初始是{},相当于创建了一个新的对象副本)。
不过要注意:Object.assign实现的是浅拷贝,如果this.gVar.$fVar里包含嵌套对象,那么嵌套对象仍然是引用类型,修改嵌套对象的属性还是会影响原对象。如果需要彻底隔离所有层级的对象,就需要用深拷贝方案(比如前面提到的JSON序列化,或者自定义深拷贝逻辑)。
内容的提问来源于stack exchange,提问作者Rachit Bhatnagar
相关产品推荐
相关产品推荐

