4

object.getElementsByTagName(tagName)forステートメントで使用すると、

for (index = 0; index < object.getElementsByTagName(tagName).length; index++) {
object.getElementsByTagName(tagName)[index].property = value;
}

ブラウザーは、ループを通過するたびに新しい nodeList オブジェクトをインスタンス化しますか?それとも、ブラウザーは毎回生成された単一のリストを参照するだけですか? それとも、リストをインスタンス化し、指定されたオブジェクトを参照し、ループを通過するたびにリストオブジェクトをアンロードしますか?

nodeList オブジェクトを変数に格納し、必要に応じて参照する方がよいかどうか疑問に思っていました。

4

5 に答える 5

1

これは、以下にリストされている理由により、はるかに優れたコードです。

var elems = object.getElementsByTagName(tagName);
for (var index = 0, len = elems.length; index < len; index++) {
    elems[index].property = value;
}
  1. getElementsByTagName()複数回呼び出すことはできません。nodeList を 1 回だけフェッチします。
  2. 効率的にするために、特定のブラウザー実装に依存していません。
  3. nodeList の長さをプリロードするので、ループのたびに再フェッチされることはありません。
  4. これは、コードを効率的にするためのより安全な方法です。
  5. より安全なコードは、あなたが尋ねた実装に関する質問を無意味にします。
于 2013-08-12T08:06:50.143 に答える
1

ブラウザは、ループを通過するたびに新しい nodeList オブジェクトをインスタンス化しますか、それとも、生成された単一のリストを毎回参照するだけですか。

getElementsByTagNameこれは、2 つの呼び出しが同じオブジェクトを返すかどうかをテストすることで簡単にテストできます。

document.getElementsByTagName('div') === document.getElementsByTagName('div')
// true

このメソッドを同じ引数で呼び出すと、実際には同じオブジェクトが返されるようですNodeList(少なくとも Firefox と Chrome では)。毎回新しいリストを生成するわけではありません

したがって、ループ内で何度も呼び出しても違いはないと思うかもしれません。ただし、私が見ているように、リストを変数に格納する理由は複数あります。

  • 各ループに不要な関数呼び出しがあります。

  • 舞台裏で実際に何が起こっているかはわかりません。同じオブジェクトが返されても、リストがドキュメントの現在の状態を反映していることを確認するプロシージャが実行されている可能性があります。これは、関数を呼び出さなかった場合には発生しません。

  • 最も重要なこと: DOM 仕様では、同じリストを返す必要がないようです。Firefox と Chrome (私がテストした場所) での動作は実装の詳細にすぎない可能性があるため、この動作には依存しません。実際、仕様では、新しいリストを返すことが明示的に述べられています。

    戻り値: 一致したすべての要素を含む新しい NodeList オブジェクト。


nodeList オブジェクトを変数に格納し、必要に応じて参照する方がよいかどうか疑問に思っていました。

はい、そうです。getElementsByTagName要素が追加または削除されたときに再度呼び出す必要はありません。これは、返さNodeListれるものがliveであるためです。つまり、ドキュメントに加えられた変更は、明示的に更新することなく、リストに直接反映されます。
リストの へのアクセスなど、特定の操作lengthによっても再評価がトリガーされます。したがって、リストを変数に保存することに加えて、長さもキャッシュすることができます。

var nodes = object.getElementsByTagName(tagName);

for (var index = 0, l = nodes.length; index < l; index++) {
    nodes[index].property = value;
}

これは、必要なものに応じて、非常に便利または非常に混乱する可能性があります。関数が呼び出された時点で存在するノードのリストのみが必要な場合は、NodeList を配列に変換する必要があります。

var nodes = Array.prototype.slice.call(object.getElementsByTagName(tagName), 0);
于 2013-08-12T07:51:19.620 に答える
0

このテストは、最初に配列が毎回長さを計算することを示しています!

var testObj = {
    getArray: function () {
        console.log( 'getting array' );
        return this._array;
    },
    _array: ['a','b','c']
};

for ( var index = 0; index < testObj.getArray().length; index++ ){
    document.write( testObj.getArray()[index] );
}

最初に要素を保存して、毎回 .length を参照するか、変数に長さを保存するだけです:)

于 2013-08-12T07:53:13.903 に答える
0

ブラウザは毎回新しいリストを生成しています。ただし、このコードはindex、実行ごとに変更するのと同じように機能します。

最初にノード リストを some に保存することをお勧めしますvar

var elements = object.getElementsByTagName(tagName);

for (index = 0; index < elements; index++) {
        elements[index].property = value;
}

あなたのアプローチは次のように見ることができます:

var index = 0;

while(index<object.getElementsByTagName(tagName))
{
  elements[index].property = value;
  index++;
}
于 2013-08-12T07:48:40.390 に答える
0

あなたはそれが何をすることを期待していましたか?あなたの心を読みますか?object.getElementsByTagName(tagName)JS プロセッサが、 (おそらく) 呼び出されるたびに同じ値を返し、したがって「ループ不変」であり、ループから引き上げることができるセマンティック情報を持つことを期待していましたか( http://enを参照)。 .wikipedia.org/wiki/Loop-invariant_code_motion )?

おそらく、ブラウザが要素の下に特定のタグ名を持つすべての要素のリストを何らかの形で「キャッシュ」し、その後の呼び出しで同じリストを返すだけだと想像したでしょうか? コードを見ずにブラウザーが内部で何を行っているかを判断するのは困難ですが、そうでない場合や、あるブラウザーがそうで別のブラウザーがそうでない場合もあります。ブラウザーが結果をキャッシュしたとしても、パフォーマンスへの影響が全体的なスキームでマイナーである可能性が高いとすれば、API を何度も呼び出すと、既に設定されている変数を参照するよりも効率が常に低下します。また、プロパティの設定など、nodelist の各要素に対して行う操作によって、キャッシュがリセットされる可能性があることも不可能ではありません。

マイナーポイントとして、リストが何度も作成されると仮定すると、リストは「アンロード」されません。JS にはそのような概念はありません。厳密に言えば「放置」状態。すぐにガベージコレクションされます。

そうです、ぜひgetElementsByTagName一度だけお電話ください。実際には、「ライブ」リストを返すため、プログラムの最初に一度呼び出すことができます (関心のあるオブジェクトとタグ名が 1 つだけであると仮定します)。https://developer.mozilla.org/en-US/docs/Web/API/element.getElementsByTagNameを参照してください。

于 2013-08-12T08:08:58.837 に答える