结论:Dart是值传递。
我们先看值传递和引用传递的定义:
值传递和引用传递,属于函数调用时参数的求值策略(Evaluation Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。值类型/引用类型,是用于区分两种内存分配方式,值类型在调用栈上分配,引用类型在堆上分配。
一个描述内存分配方式,一个描述参数求值策略,两者之间无任何依赖或约束关系。
求值策略:
值传递和引用传递的区别;
这里的改变不是指mutate, 而是change,指把一个变量指向另一个对象,而不是指仅仅改变属性或是成员什么的(如Java,所以说Java是Pass by value,原因是它调用时Copy,实参不能指向另一个对象,而不是因为被传递的东西本质上是个Value,这么讲计算机上什么不是Value?)
这些行为,与参数类型是值类型还是引用类型无关。对于值传递,无论是值类型还是引用类型,都会在调用栈上创建一个副本,不同是,对于值类型而言,这个副本就是整个原始值的复制。而对于引用类型而言,由于引用类型的实例在堆中,在栈上只有它的一个引用(一般情况下是指针),其副本也只是这个引用的复制,而不是整个原始对象的复制。
加个解释:这个时候会产生一个疑问,为什么“引用类型”的参数传递进来之后可以改变原来数据的属性?不是说不能改变原来的数据对象吗?
主要是这两个“改变”的含义不同,上面其实已经说了。如果传递策略采取的是“值传递”,它其实是原来数据的一份拷贝,值类型拷贝的是值,而引用类型copy的是指针地址。你可以直接改变值,也可以直接改变指针地址,但是都不会改变原来的数据的值或者指针地址。但是因为引用类型你拿到的是指针地址,所以,可以改变地址指向内存内的一些参数的值,但是不能让原来指向这个内存的地址的指针A改变指向。
换句话说,如果传递策略采取的是“引用策略”,那你可以直接改变传进来的原参数,一旦参数指向了B,则原参数也指向了B。
按我的理解画个草图说明下:
基本上,除了C 、C#和C++,其他的语言如java和OC、Dart等,都是只采取了值传递策略。(原因是则是为了用起来更简单,越灵活越难上手;同时还能规避很多因为此而产生的不必要的问题)