4

かなり興味深い問題に遭遇しました。以下のコードは、ログに記録されると値を与える配列を生成します[undefined × 1]this answerによると、それは配列に初期化されたインデックスがあることを意味します-この場合は1つだけです。ただし、array.push()この種の問題を正確に回避するために使用しているだけなので、ちょっと迷っています。私の知る限り、他の初期化されたインデックスよりも少なくとも 1 つ大きいインデックスを割り当てるだけで、問題が発生する可能性があります。とにかく、ここにコードがあります:

function Thing(params) {
    var that = this;

    this.OtherObject = function OtherObject(param) {
        this.param = param;
    }

    this.Foo = function Foo() {
        this.bar = [];

        this.add = function(item) {
            if (this.bar.length != 0) {
                for (var i = 0, len = this.bar.length; i < len; i++) {
                    if (this.bar[i].param <= item.param) {
                        this.bar.splice(i, 0, item);
                    }
                }
            } else {
                this.bar[0] = item;
                console.log(this.bar);
            }
        }

        this.pop = function() {
            return this.bar.pop();
        }

        this.length = function() {
            return this.bar.length;
        }
    }

    this.someFunc = function() {
        var myThing = new that.Foo();
        myThing.add(new that.OtherObject(3));

        while (myThing.length() > 0) {
            var someVar = myThing.pop();
        }
    }
}

var myThing = new Thing({
    myParam: "someValue"
});

myThing.someFunc();
​

問題を絞り込むことができるかどうかを確認するためにテスト ケースを作成しましたが、コードの 95% を再入力することになり、問題が再び発生しましたmyThing.pop()。問題の問題を示すフィドルをここで見つけることができます。

それで...何がこれを引き起こしているのかについてのアイデアはありますか? これは、実際にオブジェクトをネストした方法に問題がありますか? (これは、私の以前の質問に対するこの回答で私に与えられたパターンに従って行いました)。

ここで何をしようとしているのか疑問に思っている方のために説明すると、外側のオブジェクトを一種の名前空間のように扱っています。これは、グローバル名前空間が混乱するのを避けるために行っています (これは最終的にはパスファインディング ライブラリになります)。ここで自分の行動をまとめれば)。オブジェクトは、スタックを ing することで最も近いノード (プロパティFooが最も低いノード) を取得できるように、一種の順序付けられたリストであることを意図しています。parampop()

4

1 に答える 1

2

console.logGoogle Chrome の機能で非常に奇妙なことが起こっています。他のブラウザは、期待どおりに動作するようです。これは私が見た奇妙なことの 1 つです。 を呼び出すalert行の後にへの呼び出しを追加するとconsole.log、コンソールに異なる出力が表示されます。

console.log(this.bar);
alert(this.bar);

// [> OtherObject]

を削除するalertと、ご覧のとおり、コンソールに出力されます

// [undefined × 1] 

alertこの種のことは、何らかの競合状態または関数が引き起こしている何らかの副作用によるものです。舞台裏で何が起こっているかについての私の理論は次のとおりです。

  • このconsole.log関数は、コードが停止するまでコンソールに実際に値を記録しません。その後、キューに入れられたすべてのメッセージを記録します。キューには、ログに記録されるメッセージへの参照が含まれています。
  • this.bar配列をポップすると、最初の項目が破棄されます。ロガーは、何らかの中断がない限り、参照された値が破棄された後にメッセージを表示します。したがって、表示されます[undefined × 1]
  • 呼び出しalertによってコードが停止し、参照された値が消去される前にコンソールがメッセージをログに記録できるようになります。

これが本当に起こっていることなのかどうかはまだ完全にはわかりませんが、ある程度合理的であるように思われます. 私の理論が正しいかどうかを確認するために、さらにテストを行います。

于 2012-05-26T04:01:46.027 に答える