4

ajaxクエリを終了した後、以下のjavascriptがあります

私のすべての画像には name="pic" があります

<script type="text/javascript">
 function done() {
     var e = document.getElementsByName("pic");
     alert(e.length);
     for (var i = 0; i < e.length; i++) {
         cvi_instant.add(e[i], { shadow: 75, shade: 10 });
     }
 }

私の目標は、このライブラリを使用して画像の境界線を適用することです:

http://www.netzgesta.de/instant/

問題は、何らかの理由でこれが機能することですが、すべての画像ではなく、他のすべての画像にのみ適用されるようです。上記のコードが他のすべての要素をスキップする理由の手がかりはありますか??

編集:ループにアラートを追加しましたが、正しく 0, 1,2,3,4,5,6 になります。.

     for (var i = 0; i < e.length; i++)
     {
         alert(i);
         cvi_instant.add(e[i], { shadow: 75, shade: 10 });
     }
4

4 に答える 4

7

すべての写真ではなく、他のすべての写真にのみ適用されるようです

これは、破壊的な反復の典型的な兆候です。

私が推測しているように、関数が名前付きの要素を他の要素または複数の要素にcvi_instant.add置き換えるとどうなるか考えてみてください。pic

getElementsByName「ライブ」の NodeList を返します。これは、DOM に変更を加えるたびに最新の状態に保たれます。したがって、以前に 5 つの要素があった場合、呼び出し後cvi_instant.addは 4 つだけになります。最初のノードがなくなり、ノード 1 ~ 4 が位置 0 ~ 3 に移動します。

ここで、再びループを回ります。i++ですので、要素 1 を見ています。しかし、要素 1 は元の要素 2 でした! 元の要素 1 をスキップしました。リストの最後 (現在は半分の長さ) に到達するまで、他のすべての要素をスキップし続けます。

リストを繰り返しながら変更すると、この種の問題が発生します。反復内のプロセスが実際にリストに要素を追加すると、無限ループになることさえあります!

手っ取り早い解決策は、ループを逆方向に反復することです。次に、最後の要素を最初に実行し、他のすべての要素を元の位置に残し、スキップを発生させません。

 var e= document.getElementsByName("pic");
 for (var i= e.length; i-->0;) {
     cvi_instant.add(e[i], { shadow: 75, shade: 10 });
 }

各呼び出しで常にリストから要素を削除することがわかっている場合の別の簡単な解決策は次のとおりです。

 var e= document.getElementsByName("pic");
 while (e.length>0) {
     cvi_instant.add(e[0], { shadow: 75, shade: 10 });
 }

ドキュメントの先頭に名前を付けた新しい要素を挿入したり、途中から他の要素を削除したりするなど、ループ本体がリストに対して何でもできる場合は、最も一般的な解決策が必要です。pic少し遅くなりますが、リストの静的コピーを作成して作業することは常に安全です。

 function Array_fromList(l) {
     var a= [];
     for (var i= 0; i<l.length; i++)
         a.push(l[i]);
     return a;
 }

 var e= Array_fromList(document.getElementsByName("pic"));
 for (var i= 0; i<e.length; i++) {
     cvi_instant.add(e[i], { shadow: 75, shade: 10 });
 }
于 2009-09-22T00:49:30.090 に答える
1

こんにちは、同じ問題に遭遇しました。私のスクリプトは他のすべての要素をスキップしていました。ループ内で変数名を i から k に変更するだけで、最終的に解決しました。そのため、変数 i は getElementsByTagName によって内部的に使用され、ライブノードリストのどこにあるかを追跡し、プログラマーのインターフェースに何らかの形で漏れていると思います。だからそのバグです!:-)

于 2010-12-08T00:28:29.160 に答える
1

私の推測では、 cvi_instant.add() は、渡された値に対してインクリメントまたは反復を行っていると思います。代わりにこれを試してみてください - その方が簡単で、問題を解決できると思います:

function done() {
  var e = document.getElementsByName('pic');
  for (pic in e) { cvs_instant.add(pic, { shadow: 75, shade: 10 }); }
}
于 2009-09-22T00:35:52.800 に答える
0

- 編集:

私が以下に主張することはすべて、完全に間違っているようです。私は同じことを考えた人のためのポイントとしてこれをここに残しておきます:)私はFF3でテストしました。IE でこの動作を一度見たと主張したいのですが、おそらく何年も前のことです (考えてみると、おそらく 7 年前でした)。私の記憶力はおそらく悪いです:)

- 年:

それが正確であることが判明した場合、私の野生の推測を少し拡張するには:

メモリから、変数 ('var ...') を宣言しない場合、別の場所の変数が使用されます。

したがって、テストせずに、このコードは次のようになります。

for(var k = 0; k < 2; k++){
    f();
    alert("k: " + k);
}

function f () {
  k++;
}

同じ動作を示すはずです。TML のソリューションは、'防御的コーディング' の観点から非常に優れていると思います。私の分析が正しいことが判明した場合です。

于 2009-09-22T00:39:49.533 に答える