在 Flex 3 中,Arraycollection 通过值而不是通过引用传递到函数中
我想通过 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请参阅评估策略。
AS 使用“按对象传递”/“按对象共享传递”。也就是说,“对象”被传递(不是副本、克隆或重复),并且对该对象的任何修改都是共享的。
但是,赋值
_ac2 = _ac1
仅更改[函数的本地]参数变量的值,不会影响函数调用期间的任何变量。唯一传入的是值(“对象”),这些值是对函数调用中使用的变量(或任何任意表达式)进行求值而得到的结果。这是因为,如上所述,使用的策略是“按对象传递”,而不是(如文档所述“按引用传递”,这实际上意味着“按[引用的]值传递”) “或者只是......“经过物体”)。也就是说,术语“通过引用传递”实际上被误用,因此令人困惑。 (它在许多语言和文档中被误用。试图获得通用含义是一场艰苦的战斗。)
如果它确实是“按引用传递”,则为
_ac2
将传播出去。 (在发表评论说明 AS 如何“按引用传递”之前,请参阅顶部的链接并考虑“按引用传递”涵盖了 C# 的out/ref
、VB 的ByRef 的情况
、TSQL 的output
和 C++ 的(参考)&
——这些概念不在 AS、Javascript 或 Java 中。然而,正如原始帖子(以及附加的自我回复)中正确指出的那样,情况并非如此——结论:AS 不支持“按引用传递”; 此外,文档(令人困惑地)使用术语“通过引用传递”来表示“通过对象传递”/“通过对象共享传递”。可以通过多种方式传播更改,按(我的)顺序排序首选项:
返回新的适用值:
AC2 = doSomeTransformation(AC1)
。这通常是最干净的。避免副作用和令人惊讶的代码。如果适当地包装在对象(或数组)中,则可以返回多个值。使用闭包:
doSomeTranformation(AC1, function (newValue) { AC2 = newValue })
其中 doSomeTransformation 可能如下所示:function doSomeTransformation(_ac1, finish) { ...;完成(_ac1)}
。我通常只在回调“在函数本身的上下文中运行”时或以 CPS 风格编写代码时使用它。改变一个对象(毕竟,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#'sout/ref
, VB'sByRef
, TSQL'soutput
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:
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.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.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 likefunction 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)
"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)
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.
我看到的问题是
尝试在函数中添加该项目。
您可以在赋值后添加一个断点,然后查看 AC2 应该具有与 AC1 相同的对象。
The problem I am seeing is
Try adding the item within a function.
You can add a breakpoint in after the the assignment and see that AC2 should have the same Object as AC1.
我相信@Constantiner 是在正确的轨道上,但我认为他的解释缺乏细节;所以我将尝试更深入地解释;据我所知。如果我错了,你们可以纠正我。
如文档中所述:
因此,ArrayCollection 绝对是一个对象,而不是原始类型,因此它应该通过引用传递,并且就像通过引用传递一样。但是,ArrayCollection 的引用变量是什么?从概念上讲,它只是指向包含实际集合数据的某个内存空间的指针。这是我对一些 ASCII 艺术的尝试:
重复一下,ac1variable 是指向某个内存空间的指针。 ac2variable 是指向某些不同内存空间的指针。当您将其中之一作为参数传递给方法时,它是通过引用传递的。所以,在方法内部,你有这样的东西:
所以 ac1variable 和 ac1argument 都指向相同的内存空间;因为它们各自包含相同的指针值。然而,ac1variable和ac1argument实际上持有不同的内存空间。它们不一样。
当该方法运行此行时:
您会得到类似这样的结果:
当该方法的执行结束时,两个参数消失,原始指针变量保持不变。如果您想在方法内进行这样的直接赋值,您可以使用 this 关键字访问全局变量。这应该可以做到:
当然,如果您要访问类级别变量,这可能会破坏方法内封装的目的。
我相信编译器设计和此类事情的专家会把它当早餐吃然后吐出来。我希望我的 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:
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:
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:
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:
You get something like this:
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:
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..