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

为何索引和键均为常量时,打印值仍发生变化?(Dart/Flutter)

问题原因分析

核心问题在于对象的引用传递特性,不管是Dart还是JavaScript,对象类型(比如Map)都是按引用传递的,而非值复制。

具体执行过程拆解

  1. 首次调用exec(b)时,count=1进入else分支,执行a[1]['values'][0]['options'] = selectedOption['options'];这一步,并没有复制b['options']的内容,而是把b['options']这个对象的内存引用赋值给了a对应的字段。此时a里的options和b里的options指向内存中同一个对象。
  2. 后续修改b['options']['selected'] = 1、=2时,本质是修改这个共享对象的属性值,a里的options因为和b的options是同一个对象,所以会同步变化。
  3. 虽然首次执行后count被设为0,不会再进入else分支修改a的结构,但之前建立的引用关联并未断开,所以每次打印a[1]['values'][0]['options']['selected']时,输出的都是那个共享对象当前的selected值。

解决方案:复制对象内容而非引用

如果希望a里的options不受b后续修改的影响,需要创建新的对象副本,而非直接赋值引用。在Dart中可以使用Map.from()复制Map内容:

void main() {
  var count = 1;
  var a = {};

  exec(selectedOption) {
    if (count == 0) {
      print("NOTHING");
    } else {
      print("ELSE");
      a[1] = {};
      a[1]['values'] = [
        {
          "options": {},
        }
      ];
      // 复制对象内容,避免引用关联
      a[1]['values'][0]['options'] = Map.from(selectedOption['options']);
      count = 0;
    }
    print(a[1]['values'][0]['options']['selected']);
  }

  var b = {};
  b['options'] = {};
  b['options']['selected'] = 0;
  exec(b);
  b['options']['selected'] = 1;
  exec(b);
  b['options']['selected'] = 2;
  exec(b);
}

修改后运行输出

ELSE
0
NOTHING
0
NOTHING
0

此时a里的options是独立对象,后续修改b的options不会再影响a的值。

内容的提问来源于stack exchange,提问作者Tushar Kulkarni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:47:43