在 Flex 3 中,Arraycollection 通过值而不是通过引用传递到函数中

发布于 2024-11-05 17:51:34 字数 534 浏览 4 评论 0原文

我想通过 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;
}

I want to set arrayCollection #2 = to arrayCollection #1 via a function in flex 3. I pass both array collections to a function and set arrayCollection #2 = arrayCollection #1. However, it seems to not be passing arrayCollection #2 by reference because after the function call, arrayCollection #2 has not been changed. My understanding is that it should be passed by reference and work, am I doing something wrong? Below is the code:

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

酷遇一生 2024-11-12 17:51:34

请参阅评估策略

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

但是,赋值 _ac2 = _ac1 仅更改[函数的本地]参数变量的值,不会影响函数调用期间的任何变量。唯一传入的是值(“对象”),这些值是对函数调用中使用的变量(或任何任意表达式)进行求值而得到的结果。

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

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

可以通过多种方式传播更改,按(我的)顺序排序首选项:

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

  2. 使用闭包:doSomeTranformation(AC1, function (newValue) { AC2 = newValue }) 其中 doSomeTransformation 可能如下所示:function doSomeTransformation(_ac1, finish) { ...;完成(_ac1)}。我通常只在回调“在函数本身的上下文中运行”时或以 CPS 风格编写代码时使用它。

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

快乐编码。


适用摘录,来自评估策略

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

<块引用>

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

“通过对象调用”/“通过对象共享调用”:(但请注意其中承认这些术语的不一致/本地化的地方;术语“通过引用调用”经常被误用来暗示这些术语语义和“按值调用[引用]”在某些上下文中也表示相同的意思)

<块引用>

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

Please see Evaluation Strategy.

AS uses "pass by object" / "pass by object-sharing". That is, the "object" is passed (not a copy, clone or duplicate) and any modifications to the object are shared.

However, the assignment _ac2 = _ac1 only changes the value of the [function's local] parameter variable and will have no affect on any variables during the function invocation. The only thing passed in are the values ("objects") which result from the evaluation of the variables (or any arbitrary expression) used in the function invocation.

This is because, as stated above, the strategy used is "pass by object" and not (as the documentation states "pass by reference", which really means, "pass by value [of the reference]" or just ... "pass by object"). That is, the term "pass by reference" is actually misused and hence, confusing. (It is misused in a number of languages and documentation. It is an uphill battle trying to getting to a common meaning.)

If it were really "pass by reference" then assigning a new value to _ac2 would propagate out. (Before posing a comment saying how AS is "pass by reference", please see the link at top and consider that "pass by reference" covers the case of C#'s out/ref, VB's ByRef, TSQL's output and C++'s (reference) & -- these notions are not in AS, Javascript, or Java). However, as correctly noted in the original post (and additional self-reply), it is not the case -- conclusion: AS does not support "pass by reference"; furthermore, the documentation (confusingly) uses the term "pass by reference" to mean "pass by object" / "pass by object-sharing".

There are several ways that the change can be propagate out, ordered by order of (my) preference:

  1. Return the new applicable value: AC2 = doSomeTransformation(AC1). This generally the cleanest. Avoid side-effects and surprising code. Multiple values can be returned if wrapped in an object (or array) as appropriate.

  2. Use a closure: doSomeTranformation(AC1, function (newValue) { AC2 = newValue }) where doSomeTransformation might look like: function doSomeTransformation(_ac1, finished) { ...; finished(_ac1) }. I generally only use this when the callback "runs in context" of the function itself or when writing code in a CPS-style.

  3. Mutate an object (AS is "pass by object", after all). This is very icky, but it will work.
    var blah = {AC2: null}; doSomeTransformation(ac1, blah); ...; laterOn(blah.AC2) where doSomeTransformation might look look like function doSomeTransformation(_ac1, b) { ...; b.AC2 = _ac1; }. Not recommended in general.

Happy coding.


Applicable excerpts, from Evaluation Strategy:

"call by reference": (my main argument for "call by reference" being used incorrectly is that it already has a well-defined meaning; the overloaded term adopted by some languages such as AS and Python just adds confusion)

In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify the variable used as argument- something that will be seen by its caller.

"call by object" / "call by object-sharing": (but pay heed to where it acknowledges the inconsistency/localization of these terms; the term "call by reference" is often misused to imply these semantics and "call by value [of the reference]" is used in some contexts to also mean the same thing)

The semantics of call-by-sharing differ from call-by-reference in that assignments to function arguments within the function aren't visible to the caller (unlike by-reference semantics), so e.g. if a variable was passed, it is not possible to simulate an assignment on that variable in the caller's scope. However since the function has access to the same object as the caller (no copy is made), mutations to those objects, if the objects are mutable, within the function are visible to the caller, which may appear to differ from call-by-value semantics.

随梦而飞# 2024-11-12 17:51:34

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

THe function arguments in ActionScript pass by value, not by reference. It is absolutely the same as in Java. You can read in details here.

深海夜未眠 2024-11-12 17:51:34

我看到的问题是

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 相同的对象。

The problem I am seeing is

var AC1.addItem(someObject);

Try adding the item within a function.

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 );
}

You can add a breakpoint in after the the assignment and see that AC2 should have the same Object as AC1.

单调的奢华 2024-11-12 17:51:34

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

文档中所述:

在 ActionScript 3.0 中,所有参数都是
通过引用传递,因为所有
值存储为对象。然而,
属于原语的对象
数据类型,包括布尔值、
Number、int、uint 和 String,有
制作它们的特殊运算符
表现得好像他们经过一样
值。

因此,ArrayCollection 绝对是一个对象,而不是原始类型,因此它应该通过引用传递,并且就像通过引用传递一样。但是,ArrayCollection 的引用变量是什么?从概念上讲,它只是指向包含实际集合数据的某个内存空间的指针。这是我对一些 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 艺术在多个浏览器/机器/操作系统/等之间保持一致。

I believe that @Constantiner is on the right track, but I think his explanation is lacking detail; so I'm going to try to explain with a bit more depth; as best I understand it. Ya'll can correct me if I'm wrong.

As stated in the docs:

In ActionScript 3.0, all arguments are
passed by reference, because all
values are stored as objects. However,
objects that belong to the primitive
data types, which includes Boolean,
Number, int, uint, and String, have
special operators that make them
behave as if they were passed by
value.

So, an ArrayCollection is definitely an object, and not a primitive type, so it should be passed by reference and act like it was passed by reference. But, what is your reference variable to the ArrayCollection. Conceptually it just a pointer to some memory space that contains the actual Collection data. Here is my attempt at some ASCII art:

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

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

to repeat, ac1variable is a pointer to some memory space. ac2variable is a pointer to some different memory space. When you pass one of them into a method as an argument it is passed by reference. So, inside the method, you have something like this:

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

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

So both ac1variable and ac1argument point at the same memory space; because they each contain the same pointer value. However, ac1variable and ac1argument are actually holding different memory spaces. They are not the same.

When the method runs this line:

_ac2 = _ac1;

You get something like this:

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

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

When the method's execution ends, the two arguments go away, and the original pointer variables remain unchanged. If you want to do a direct assignment like this inside a method, you can access the global variable using the this keyword. This should do it:

   this._ac2 = _ac1;

Of course, that can defeat the purpose of encapsulation inside a method if you're accessing class level variables.

I'm sure an expert on compiler design and such things will eat this for breakfast and spit it up. I hope my ASCII art is consistent across multiple browsers / machines / OSes / etc..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文