10

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

目的:

var object:Object = {

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

};

环形:

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

结果:

东西:帽子
事情:1
另一个:[对象精灵]

然而,选择属性的顺序似乎有所不同,并且与我能想到的任何东西都不匹配,例如按字母顺序排列的属性名称、它们的创建顺序等。事实上,如果我在不同的地方尝试了几次不同的时间,顺序完全不同。

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

4

2 回答 2

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

正如你所看到的,当有一个合法的属性(对象)要返回时,它是从类中查找的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;
}

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

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

来源
对于那些可能想要获取 Flash 播放器的开源部分的源代码的人,您可以从以下 mercurial 存储库中获取它(您可以像 github 一样下载 zip 中的 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 的工作原理,所以我想我也会包括它。

于 2012-04-10T06:40:36.840 回答
7

这种行为已记录在案(强调我的):

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

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

我不相信有办法以特定顺序访问属性,除非您以某种方式存储该顺序。

于 2012-04-10T05:48:41.150 回答