10

我想通过 flex 3 中的函数将 arrayCollection #2 = 设置为 arrayCollection #1。我将两个数组集合都传递给一个函数并设置 arrayCollection #2 = arrayCollection #1。但是,它似乎没有通过引用传递 arrayCollection #2,因为在函数调用之后,arrayCollection #2 没有改变。我的理解是应该通过引用和工作传递,我做错了吗?下面是代码:

var AC1:ArrayCollection = new ArrayCollection;
var AC1.addItem(someObject);

var AC2:ArrayCollection = new ArrayCollection;

setAC2(AC1,AC2);
// AC2 is not set to AC1 after the function


private function setAC2(_ac1:ArrayCollection, _ac2:ArrayCollection):void
{
    _ac2 = _ac1;
}
4

4 回答 4

6

请参阅评估策略

AS 使用“传递对象”/“传递对象共享”。也就是说,传递“对象”(不是副本、克隆或复制),并且对对象的任何修改都是共享的

但是,赋值_ac2 = _ac1只会改变 [function's local] 参数变量的值,不会影响函数调用期间的任何变量。唯一传入的是函数调用中使用的变量(或任何任意表达式)的评估结果的值(“对象”)。

这是因为,如上所述,使用的策略是“按对象传递”而不是(如文档所述“按引用传递”,这实际上意味着“按 [引用的] 值传递”或只是......“通过对象”)。也就是说,“通过引用传递”一词实际上被误用,因此令人困惑。(它在许多语言和文档中被滥用。这是一场试图获得共同含义的艰苦战斗。)

如果它真的是“通过引用传递”,那么分配一个新值_ac2将会传播出去。(在发表评论说 AS 是如何“通过引用传递”之前,请查看顶部的链接并考虑“通过引用传递”涵盖 C# out/ref、VB ByRef、TSQLoutput和 C++(参考)的&情况——这些概念不在AS、Javascript 或 Java)。然而,正如原帖(以及额外的自我回复)中正确指出的那样,事实并非如此——结论:AS 不支持“通过引用传递”;此外,文档(令人困惑)使用术语“按引用传递”来表示“按对象传递”/“按对象共享传递”。

有几种方法可以传播更改,按(我的)偏好顺序排列:

  1. 返回新的适用值:AC2 = doSomeTransformation(AC1)。这通常是最干净的。避免副作用和令人惊讶的代码。如果适当地包装在对象(或数组)中,则可以返回多个值。

  2. 使用闭包:doSomeTranformation(AC1, function (newValue) { AC2 = newValue })doSomeTransformation 可能看起来像:function doSomeTransformation(_ac1, finished) { ...; finished(_ac1) }。我通常只在函数本身的回调“在上下文中运行”或以 CPS 样式编写代码时使用它。

  3. 改变一个对象(毕竟,AS 是“通过对象”)。这很恶心,但它会起作用。 var blah = {AC2: null}; doSomeTransformation(ac1, blah); ...; laterOn(blah.AC2)doSomeTransformation 可能看起来像的地方function doSomeTransformation(_ac1, b) { ...; b.AC2 = _ac1; }。一般不推荐。

快乐编码。


适用摘录,来自评估策略

“引用调用”:(我对“引用调用”使用不当的主要论据是它已经具有明确定义的含义;某些语言(如 AS 和 Python)采用的重载术语只会增加混乱)

在按引用调用评估(也称为按引用传递)中,函数接收对用作参数的变量的隐式引用,而不是其值的副本。这通常意味着函数可以修改用作参数的变量——调用者将看到的东西

“按对象调用”/“按对象共享调用”:(但要注意它承认这些术语的不一致/本地化的地方;术语“引用调用”经常被误用于暗示这些语义和“按值调用 [参考文献]”在某些情况下也表示相同的意思)

共享调用的语义与引用调用的不同之处在于函数内函数参数的赋值对调用者不可见(与引用语义不同),因此例如,如果传递了一个变量,则它不是可以在调用者的范围内模拟对该变量的赋值。但是,由于该函数可以访问与调用者相同的对象(不进行复制),因此如果对象是可变的,则对这些对象的突变对调用者是可见的,这可能看起来与 call-by-价值语义。

于 2011-05-07T05:56:05.987 回答
3

ActionScript 中的函数参数按值传递,而不是按引用传递。它与 Java 中的完全一样。您可以在此处详细阅读。

于 2011-05-06T22:29:06.657 回答
1

我看到的问题是

var AC1.addItem(someObject);

尝试在函数中添加项目。

var AC1:ArrayCollection = new ArrayCollection;
var AC2:ArrayCollection = new ArrayCollection;

addItemToArrayCollection( AC1 );
setAC2(AC1,AC2);
// AC2 should be pointing to the ArrayCollection that AC1 is pointing to.

private function setAC2(_ac1:ArrayCollection, _ac2:ArrayCollection):void
{
   _ac2 = _ac1;
}

private function addItemToArrayCollection( arrayCollection:ArrayCollection ):void
{
  arrayCollection.addItem( someObject );
}

您可以在分配后添加一个断点,并看到 AC2 应该与 AC1 具有相同的 Object。

于 2011-05-07T01:49:05.317 回答
1

我相信@Constantiner 是在正确的轨道上,但我认为他的解释缺乏细节;所以我将尝试更深入地解释一下;据我所知。如果我错了,你们可以纠正我。

文档中所述

在 ActionScript 3.0 中,所有参数都通过引用传递,因为所有值都存储为对象。但是,属于基本数据类型(包括 Boolean、Number、int、uint 和 String)的对象具有特殊的运算符,使它们的行为就像按值传递一样。

因此,ArrayCollection 绝对是一个对象,而不是原始类型,因此它应该通过引用传递,并且就像通过引用传递一样。但是,您对 ArrayCollection 的引用变量是什么。从概念上讲,它只是一个指向包含实际 Collection 数据的内存空间的指针。这是我对一些 ASCII 艺术的尝试:

                  |---|
 ac1(variable)--> |   | (ActualArrayCollection1)
                  |---|

                  |---|
 ac2(variable)--> |   | (ActualArrayCollection2)
                  |---|

重复一遍,ac1variable 是指向某个内存空间的指针。ac2variable 是指向一些不同内存空间的指针。当您将其中一个作为参数传递给方法时,它是通过引用传递的。所以,在方法内部,你有这样的东西:

 ac1(variable)--> |---|
 ac1(argument)--> |   | (ActualArrayCollection1)
                  |---|

 ac2(variable)--> |---|
 ac2(argument)--> |   | (ActualArrayCollection2)
                  |---|

所以 ac1variable 和 ac1argument 都指向同一个内存空间;因为它们每个都包含相同的指针值。然而,ac1variable 和ac1argument 实际上持有不同的内存空间。他们不一样。

当方法运行此行时:

_ac2 = _ac1;

你会得到这样的东西:

 ac1(variable)--> |---|
 ac1(argument)--> |   | (ActualArrayCollection1)
 ac2(argument)--> |---|

 ac2(variable)--> |---|
                  |   | (ActualArrayCollection2)
                  |---|

当方法执行结束时,两个参数消失,原始指针变量保持不变。如果你想在方法中进行这样的直接赋值,你可以使用 this 关键字访问全局变量。这应该这样做:

   this._ac2 = _ac1;

当然,如果您正在访问类级变量,这可能会破坏方法内部封装的目的。

我相信编译器设计方面的专家会在早餐时吃掉这个然后吐出来。我希望我的 ASCII 艺术在多个浏览器 / 机器 / 操作系统 / 等上是一致的。

于 2011-05-07T02:38:44.107 回答