ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript での for ループのいくつかの使用法の比較とパフォーマンスを向上させる方法

JavaScript での for ループのいくつかの使用法の比較とパフォーマンスを向上させる方法

伊谢尔伦
伊谢尔伦オリジナル
2018-05-18 15:45:023651ブラウズ

for ループは、js 内のオブジェクトや配列を走査するときに役立ちます。具体的な操作の詳細を以下にいくつか紹介します。

は一般に次のように書かれます:

for(var i = 0;i< arr.length;i++) {
 var a = arr[i];
 //...
 }

これは一般的なループの正のシーケンスです。この方法で記述することの欠点は誰もが知っています。arr から長さを取得して、毎回 i と比較するのはパフォーマンスの無駄です (また、arr の長さが動的に変化すると、無限ループが発生します)。このループを改善する方法は、変数を使用して arr.length を保存することです: arr.length

for(var i = 0, al = arr.length;i< al;i++) {
 var a = arr[i];
 //...
 }

这样比第一种可以略微提升点性能,要是数组长,可以提升更多。

不过这样写就多了个变量al,且这个变量只在用来与i对比的时候有用,看着有点鸡肋。

如果循环顺序对你不重要,那你可以尝试倒序循环:

for(var i = arr.length-1;i > -1;i--) {
 var a = arr[i];
 //...
 }

这样一来变量少些,且还缓存过arr长度,性能也不错。但这里的代码写得有点拙劣(我故意的),首先是i = arr.length-1(居然要-1,靠),然后是循环继续执行的条件i > -1,都让有洁癖的人无法忍受。

下面是我常用的倒序for循环写法:

for(var i = arr.length;i--;) {
 var a = arr[i];
 //...
 }

这已经非常精简了。原理需要理解一下:for循环继续执行的条件,是;;之间的这个判断要为真,而这里的i–,在第一次循环进来的时候,i=arr.length,i–值不变(为什么不变?因为要在for循环体里面,才会发现i变了);当i=1时,i- -还是1,但进入循环体后,就是0了,所以可以正常执行最后一次循环;当i=0时,i–还是0,而0已经不为真了,所以循环就不会继续执行了。

大家注意到上面的所有代码的for循环体里,都有个var a = arr[i] ,用来取出当前循环到的数组项。这实际上也是种浪费,且jsLint等会告诉你:不要在循环里声明变量。。。

倒序的for可以精简至斯,但我就是要正序,而且要效率高,变量少,怎么办?

如下:

for(var i = 0, a;a = arr[i++];) {
 //...
 }

这种写法好处在于:几乎不可避免的arr.length不见了,前面说的取出当前循环到的数组项的那一句也不见了。

原理:

a = arr[i++] ,在这里作为循环能执行的条件,注意这里只有一个=号,所以这不是判断句,是赋值语句,就是把arr[i++]赋给a,然后判断a是不是真值。i++与i–的原理类型我就不说了,只说当i++已经超过数组的长度时,循环肯定要停止才行,而这里真的就停止了,为什么?因为a=arr[i++] rrreee

これにより、最初の方法と比較してパフォーマンスがわずかに向上します。配列が長い場合は、さらにパフォーマンスを向上させることができます。 。

しかし、このように書くと余分な変数 al が追加され、この変数は i と比較した場合にのみ役に立ち、少し役に立たないように思えます。

ループ順序が重要でない場合は、逆順序ループを試すことができます:


rrreee

この方法では、変数が少なくなり、arr の長さがキャッシュされ、パフォーマンスも良好になります。しかし、ここでのコードは少し書き方が悪く (私は意図的にそうしました)、最初は i = arr.length-1 (実際には -1 が必要です) です。ループが実行を継続するための条件は、i > - 1 です。それらはすべて、潔癖症の人にとっては耐えられません。


以下は私がよく使用する逆順のループ記述方法です:

rrreee

これはすでに非常に合理化されています。原理を理解する必要があります。for ループが実行を継続するための条件は、;; と、最初のループが入ったときの i- の間の判定が true であることです。i=arr.lengthコード >、i- 値は変更されません (なぜ変更されないのでしょうか? i=1 の場合、i- - は 1 のままですが、ループに入った後は for ループ本体に入らなければなりません)。 body、それは 0 です。したがって、最後のループは正常に実行できます。i=0 の場合、i– は依然として 0 であり、0 は真ではなくなるため、ループは実行を継続しません。

上記のすべてのコードの for ループ本体に、現在ループされている配列項目を取り出すために使用される var a = arr[i] があることに誰もが気づきました。これは実際には無駄であり、jsLint やその他の言語では、ループ内で変数を宣言しないでくださいと通知されます。 。 。

逆順の for はこれに簡略化できますが、順方向にしたいだけで、効率的で変数が少ない必要があります。どうすればよいですか?

    は次のとおりです:
  1. rrreee

    この書き方の利点は、ほぼ避けられない arr.length が欠落していることと、現在ループされている配列項目を取り出すことに関する上記の文も欠落していることです。ない。

  2. 原則:

  3. a = arr[i++] 、ここではループが実行される条件として使用されます。ここには = 記号が 1 つしかないため、これは ではないことに注意してください。判定文ですが、代入文、つまり arr[i++] を a に代入し、a が真の値であるかどうかを判定します。 i++ と i– の基本的な型については説明しません。i++ が配列の長さを超えた場合、ループは停止する必要があることだけを述べておきます。実際にここで停止するのはなぜでしょうか。 a=arr[i++] であるため、配列自体の長さを超える項目を取得した場合は、未定義のみが取得され、未定義は false 値となり、ループ条件は失敗します。

もちろん、この方法で書くことの欠点も明らかです:


1. arr の長さが動的に変化すると、無限ループが発生します。これは、arr.length をキャッシュしたことがないためです。


2. ループが数値の配列の場合、取り出した項目(つまり a の値)が 0 の場合、ループは終了します(0 は偽の値であるため)。

3. 配列内の項目が false 値(空の文字列、0、null、未定義を含む)の場合もループは終了します🎜🎜 したがって、この書き方を使用する場合は、上記を除外するのが最善です使用状況。 🎜🎜この原則は逆順ループでも使用できます。 🎜🎜🎜最後に皆さんへのアドバイス: 🎜🎜🎜🎜🎜コードの合理化は高効率を意味するものではありません!🎜🎜🎜🎜コードを意図的に合理化するためだけにパフォーマンスを落とさないでください🎜🎜🎜🎜🎜 ちなみに、こちらfor ループのパフォーマンスを向上させるためのいくつかのポイントがあります:🎜 🎜🎜 1. 適切なタイミングでブレークする必要がない場合は、ブレークアウト条件を追加する必要があります。 🎜🎜🎜 2. for ループ本体で変数を宣言しないでください (var を 1 回使用し、値を複数回代入することをお勧めします) 🎜🎜🎜 2. 配列の長さをキャッシュし、使用する変数はできるだけ少なくします 🎜

以上がJavaScript での for ループのいくつかの使用法の比較とパフォーマンスを向上させる方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。