带嵌套地图的 Dart 传播运算符

Dart spread operator with nested map

为什么 Dart 中的展开运算符不克隆嵌套映射?此示例显示两个克隆上的“嵌套”映射指的是同一对象。

    test("test map", () {
      // Define sourceA
      var sourceA = {
        "nested": {
          "value": 10
        }
      };

      // Define sourceB
      var sourceB = {
        "sourceA": {...sourceA}
      };

      // Clone both sources into two new maps
      var m1 = {...sourceA};
      var m2 = {...sourceB};

      print(m2["sourceA"]!["nested"] == m1["nested"]); // prints true

      // Check hash codes
      print(m2["sourceA"]!["nested"].hashCode); // prints 480486640
      print(m1["nested"].hashCode);             // prints 480486640

      // Change the nested value of m2
      m2["sourceA"]!["nested"]!["value"] = 11;

      // Observe it has been changed in m1
      print(m1["nested"]!["value"]); // prints 11
    });

我想要实现的是能够仅更改其中一个克隆的嵌套属性。

Spread 运算符使用其引用(也称为浅拷贝)复制集合。要了解更多关于浅拷贝和深拷贝之间的区别,您可以阅读 here。这在许多语言中都很常见。

在 Dart 中有多种方法可以进行深拷贝。这是一个基于您的代码的示例:

import 'dart:convert';

main(){
  // Define sourceA
      var sourceA = {
        "nested": {
          "value": 10
        }
      };

      // Define sourceB
      var sourceB = {
        "sourceA": {...sourceA}
      };
  

      // Clone both sources into two new maps
      var m1 = {...sourceA};
      var m2 = {...sourceB};
      var m3 = json.decode(json.encode(sourceB)); // deep copy

      print(m2["sourceA"]!["nested"] == m1["nested"]); // prints true
      print(m3["sourceA"]!["nested"] == m1["nested"]); // prints false

      // Check hash codes
      print(m2["sourceA"]!["nested"].hashCode); // prints 418854379
      print(m3["sourceA"]!["nested"].hashCode); // prints 892131505
      print(m1["nested"].hashCode);             // prints 418854379

      // Change the nested value of m3
      // m2["sourceA"]!["nested"]!["value"] = 11;
      m3["sourceA"]!["nested"]!["value"] = 11;

      // Observe it has been changed in m1
      print(m1["nested"]!["value"]); // prints 10
}