当我在AS3中使用(i in object)时发生了什么?

Mar*_*rty 10 actionscript-3

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

宾语:

var object:Object = {

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

};
Run Code Online (Sandbox Code Playgroud)

环:

for(var i:String in object)
{
    trace(i + ": " + object[i]);
}
Run Code Online (Sandbox Code Playgroud)

结果:

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

然而,选择属性的顺序似乎有所不同,并且永远不会匹配我能想到的任何内容,例如字母属性名称,创建它们的顺序等等.事实上,如果我在不同的地方尝试几次不同的时间,顺序完全不同.

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

小智 9

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

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,当有一个合法的属性(对象)要返回时,它会从ScriptObject类中查找,特别是nextName()方法.如果我们在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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

来源
对于那些可能想要获得Flash播放器开源部分源代码的人,你可以从以下的mercurial存储库中获取它(你可以像github一样下载一个zipstore的snapshop,这样你就不必安装了水银):

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

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

虽然我对此感兴趣,但也可能会对此感兴趣:http://code.google.com/p/redtamarin/.它是AVM的分支(并且相当成熟)版本,可用于编写服务器端动作脚本.整洁的东西,有大量的信息,可以深入了解AVM的运作情况,所以我想我也会把它包括在内.


Bol*_*ock 7

这种行为被记录在案(重点煤矿):

for..in通过对象的属性循环迭代,或阵列中的元素.例如,您可以使用for..in循环来遍历通用对象的属性(对象属性不以任何特定顺序保存,因此属性可能以看似随机的顺序出现)

如何存储和检索属性似乎是一个实现细节,文档中没有介绍.正如ToddBFisher在评论中提到的那样,通常用于实现关联数组的数据结构是哈希表.在本页中甚至提到了AS3中的关联数组,如果你检查Ascension Systems所示的AVM代码,你会发现这样的实现.如上所述,在典型的哈希表中没有顺序或排序的概念.

我不相信有一种方法可以按特定顺序访问属性,除非您以某种方式存储该订单.