当我在 AS3 中使用 for(i in object) 时发生了什么? [英] What's happening when I use for(i in object) in AS3?

查看:22
本文介绍了当我在 AS3 中使用 for(i in object) 时发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在 AS3 中迭代 Object 的属性,您可以像这样使用 for(var i:String in object):

对象:

var object:Object = {事情:1,东西:帽子",另一个:new Sprite()};

循环:

for(var i:String in object){跟踪(我+:"+对象[我]);}

结果:

<前>东西:帽子东西:1另一个:[对象精灵]

然而,选择属性的顺序似乎各不相同,永远不会匹配我能想到的任何东西,例如按字母顺序排列的属性名称、创建它们的顺序等.事实上,如果我尝试几次不同的时间不同的地方,顺序完全不同.

是否可以按给定顺序访问属性?这里发生了什么?

解决方案

我发布这个答案只是为了赞美 BoltClock 的答案 通过直接查看 Flash Player 源代码获得一些额外的见解.我们实际上可以看到专门提供此功能的 AVM 代码,它是用 C++ 编写的.我们可以在ArrayObject.cpp里面看到如下代码:

//迭代器支持 - for in, for eachAtom ArrayObject::nextName(int index){AvmAssert(索引> 0);int密集长度 = (int)getDenseLength();如果(索引<=denseLength){AvmCore *core = this->core();返回核心-> intToAtom(index-1);}别的{返回 ScriptObject::nextName(索引 - 密集长度);}}

如您所见,当有合法的属性(对象)要返回时,它是从 ScriptObject 类中查找的,特别是 nextName() 方法.如果我们查看 ScriptObject.cpp 中的这些方法:

Atom ScriptObject::nextName(int index){AvmAssert(traits()->needsHashtable());AvmAssert(索引> 0);InlineHashtable *ht = getTable();if (uint32_t(index)-1 >= ht->getCapacity()/2)返回 nullStringAtom;const Atom* atom = ht->getAtoms();原子 m = ht->removeDontEnumMask(atoms[(index-1)<<1]);如果 (AvmCore::isNullOrUndefined(m))返回 nullStringAtom;返回 m;}

我们确实可以看到,正如人们在此处指出的那样,VM 正在使用哈希表.然而,在这些函数中提供了一个特定的索引,乍一看,这表明必须有特定的排序.

如果您深入挖掘(我不会在此处发布所有代码),for in/for 每个功能中涉及来自不同类的大量方法,其中之一是方法 ScriptObject::nextNameIndex() 基本上拉出整个哈希表,并开始为表中的有效对象提供索引,并增加参数中提供的原始索引,只要下一个值指向有效对象.如果我的解释是正确的,这将是您随机查找背后的原因,我认为这里没有任何方法可以在这些操作中强制使用标准化/有序映射.

来源
对于那些可能想要获取 Flash Player 的开源部分的源代码的人,您可以从以下 mercurial 存储库中获取它(您可以像 github 一样下载 zip 格式的 snapshop,这样您就不必安装 mercurial):

http://hg.mozilla.org/tamarin-central - 这是稳定"或发布"存储库

http://hg.mozilla.org/tamarin-redux - 这是开发分支.可在此处找到 AVM 的最新更改.这包括对 Android 等的支持.Adobe 仍在更新和开源 Flash Player 的这些部分,因此它是当前和官方的好东西.

当我在做的时候,这可能也很有趣:http://code.google.com/p/redtamarin/.它是 AVM 的一个分支(并且相当成熟)版本,可用于编写服务器端动作脚本.整洁的东西,有大量的信息,可以深入了解 AVM 的工作原理,所以我想我也应该包括它.

To iterate over the properties of an Object in AS3 you can use for(var i:String in object) like this:

Object:

var object:Object = {

    thing: 1,
    stuff: "hats",
    another: new Sprite()

};

Loop:

for(var i:String in object)
{
    trace(i + ": " + object[i]);
}

Result:

stuff: hats
thing: 1
another: [object Sprite]

The order in which the properties are selected however seems to vary and never matches anything that I can think of such as alphabetical property name, the order in which they were created, etc. In fact if I try it a few different times in different places, the order is completely different.

Is it possible to access the properties in a given order? What is happening here?

解决方案

I'm posting this as an answer just to compliment BoltClock's answer with some extra insight by looking directly at the flash player source code. We can actually see the AVM code that specifically provides this functionality and it's written in C++. We can see inside ArrayObject.cpp the following code:

// Iterator support - for in, for each
Atom ArrayObject::nextName(int index)
{
    AvmAssert(index > 0);

    int denseLength = (int)getDenseLength();
    if (index <= denseLength)
    {
        AvmCore *core = this->core();
        return core->intToAtom(index-1);
    }
    else
    {
        return ScriptObject::nextName (index - denseLength);
    }
}

As you can see when there is a legitimate property (object) to return, it is looked up from the ScriptObject class, specifically the nextName() method. If we look at those methods within ScriptObject.cpp:

Atom ScriptObject::nextName(int index)
{
    AvmAssert(traits()->needsHashtable());
    AvmAssert(index > 0);

    InlineHashtable *ht = getTable();
    if (uint32_t(index)-1 >= ht->getCapacity()/2)
        return nullStringAtom;
    const Atom* atoms = ht->getAtoms();
    Atom m = ht->removeDontEnumMask(atoms[(index-1)<<1]);
    if (AvmCore::isNullOrUndefined(m))
        return nullStringAtom;
    return m;
}

We can see that indeed, as people have pointed out here that the VM is using a hash table. However in these functions there is a specific index supplied, which would suggest, at first glance, that there must then be specific ordering.

If you dig deeper (I won't post all the code here) there are a whole slew of methods from different classes involved in the for in/for each functionality and one of them is the method ScriptObject::nextNameIndex() which basically pulls up the whole hash table and just starts providing indices to valid objects within the table and increments the original index supplied in the argument, so long as the next value points to a valid object. If I'm right in my interpretation, this would be the cause behind your random lookup and I don't believe there would be any way here to force a standardized/ordered map in these operations.

Sources
For those of you who might want to get the source code for the open source portion of the flash player, you can grab it from the following mercurial repositories (you can download a snapshop in zip like github so you don't have to install mercurial):

http://hg.mozilla.org/tamarin-central - This is the "stable" or "release" repository

http://hg.mozilla.org/tamarin-redux - This is the development branch. The most recent changes to the AVM will be found here. This includes the support for Android and such. Adobe is still updating and open sourcing these parts of the flash player, so it's good current and official stuff.

While I'm at it, this might be of interest as well: http://code.google.com/p/redtamarin/. It's a branched off (and rather mature) version of the AVM and can be used to write server-side actionscript. Neat stuff and has a ton of information that gives insight into the workings of the AVM so I thought I'd include it too.

这篇关于当我在 AS3 中使用 for(i in object) 时发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆