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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:13:47