10

AS3の のプロパティを反復処理するには、次のようObjectに使用できます。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
another: [オブジェクト スプライト]

ただし、プロパティが選択される順序はさまざまであるように見え、アルファベット順のプロパティ名、作成された順序など、私が考えることができるものとは決して一致しません。実際、別の場所で数回試してみると、順番が全然違います。

特定の順序でプロパティにアクセスすることは可能ですか? ここで何が起きてるの?

4

2 に答える 2

9

フラッシュ プレーヤーのソース コードを直接見て、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 each 機能に関与するさまざまなクラスのメソッドが多数あり、そのうちの 1 つは、ScriptObject::nextNameIndex()基本的にハッシュ テーブル全体をプルアップするメソッドであり、次の値が有効なオブジェクトを指している限り、テーブル内の有効なオブジェクトへのインデックスの提供を開始し、引数で提供された元のインデックスをインクリメントします。私の解釈が正しければ、これがランダムルックアップの背後にある原因であり、これらの操作で標準化/順序付けされたマップを強制する方法はないと思います。

ソース
Flash Player のオープン ソース部分のソース コードを入手したい方は、次の mercurial リポジトリから入手できます (github のような zip 形式のスナップショップをダウンロードできるので、インストールする必要はありません)。水銀):

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 の仕組みについての洞察を与える情報がたくさんあるので、それも含めたいと思いました。

于 2012-04-10T06:40:36.840 に答える
7

この動作は文書化されています(強調は私のものです):

for..inループは、オブジェクトのプロパティまたは配列の要素を反復処理します。たとえば、for..inループを使用して汎用オブジェクトのプロパティを反復処理できます(オブジェクトのプロパティは特定の順序で保持されないため、プロパティは一見ランダムな順序で表示される場合があります)。

プロパティがどのように保存および取得されるかは、実装の詳細のように見えますが、ドキュメントには記載されていません。ただし、ToddBFisher がコメントで言及しているように、連想配列を実装するために一般的に使用されるデータ構造はハッシュ テーブルです。このページでは AS3 の連想配列についても言及されており、Ascension Systems が示すように AVM コードを調べると、まさにそのような実装が見つかります。説明したように、一般的なハッシュ テーブルには順序や並べ替えの概念はありません。

何らかの方法でその順序を保存しない限り、特定の順序でプロパティにアクセスする方法があるとは思いません。

于 2012-04-10T05:48:41.150 に答える