8

私は最近、このJavaScriptコードに出くわしました。

if (",>=,<=,<>,".indexOf("," + sCompOp + ",") != -1)

このテストを書くために私がしたであろうので、私は興味をそそられました:

if (/(>=|<=|<>)/.test(sCompOp))

これは単なる文体の違いですか、それとも他のコードの作成者は私が知らない最適化について何か知っていますか?または、これを行う、または正規表現を使用しない別の正当な理由があるかもしれません...?

これを使用String.indexOf()するのは少し読みにくいように思えますが(ただし、正規表現にはかなり慣れています)、同等の正規表現を作成するよりも「優れている」場合がありますか?

「より良い」ことによって、より速くまたはより効率的になる可能性があります(ただし、明らかにそれはブラウザのJavaScriptエンジンに依存します)、または私が気付いていない他の理由。誰かが私を啓発できますか?

4

5 に答える 5

11

いくつかのテストを実行しました。最初の方法はわずかに高速ですが、非常に長い文字列になる可能性がある場合を除いて、頻繁に使用しても実際の違いを生むには十分ではありません。sCompOp最初のメソッドは固定長の文字列を検索するため、その実行時間は取得の長さに関係なく非常に安定していますsCompOpが、2 番目のメソッドは の全長にわたって反復する可能性がありsCompOpます。

また、2 番目の方法は、無効な文字列に一致する可能性があります。「何とか何とか <= 何とか何とか」はテストを満たします...

他の場所で演算子を解析する作業を行っている可能性が高いことを考えると、どちらのエッジケースも問題になるとは思えません。ただし、そうでない場合でも、式を少し変更するだけで両方の問題が解決します。

/^(>=|<=|<>)$/

テスト コード:

function Time(fn, iter)
{
   var start = new Date();
   for (var i=0; i<iter; ++i)
      fn();
   var end = new Date();
   console.log(fn.toString().replace(/[\r|\n]/g, ' '), "\n : " + (end-start));
}

function IndexMethod(op)
{
   return (",>=,<=,<>,".indexOf("," + op + ",") != -1);
}

function RegexMethod(op)
{
   return /(>=|<=|<>)/.test(op);
}

function timeTests()
{
   var loopCount = 50000;
   
   Time(function(){IndexMethod(">=");}, loopCount);
   Time(function(){IndexMethod("<=");}, loopCount);
   Time(function(){IndexMethod("<>");}, loopCount);
   Time(function(){IndexMethod("!!");}, loopCount);
   Time(function(){IndexMethod("the quick brown foxes jumped over the lazy dogs");}, loopCount);
   Time(function(){IndexMethod("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");}, loopCount);

   Time(function(){RegexMethod(">=");}, loopCount);
   Time(function(){RegexMethod("<=");}, loopCount);
   Time(function(){RegexMethod("<>");}, loopCount);
   Time(function(){RegexMethod("!!");}, loopCount);
   Time(function(){RegexMethod("the quick brown foxes jumped over the lazy dogs");}, loopCount);
   Time(function(){RegexMethod("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");}, loopCount);
}

timeTests();

IE6、FF3、Chrome 0.2.149.30 でテスト済み

于 2008-10-08T16:27:19.953 に答える
3

パフォーマンスや最適化の問題ではないかと思います。そのコードの作成者は、正規表現に慣れていないか、慣れていなかったのではないかと思います。また、オブジェクトのプロパティを利用するためにカンマ区切りの文字列が分割されていないことにも注意してください。これは、言語に慣れていない可能性もあります。

たとえば、使用可能な演算子のカンマ区切りリスト内の演算子をテストする別の方法は、使用可能な演算子のカンマ区切りリストを分割し、プロパティとして演算子を使用してオブジェクトの 1 回限りの初期化を行うことです。

var aOps = ">=,<=,<>".split(",");
var allowableOps = {};
for (var iLoop = 0; iLoop < aOps.length; iLoop++) {
  allowableOps[aOps[iLoop]] = true;
} //for

この小さな初期化オーバーヘッドは、迅速なルックアップを行う機能によって相殺される可能性があります。

if (allowableOps[sCompOp]) { ... }

もちろん、これは全体的に遅くなる可能性がありますが、間違いなくクリーンなアプローチです。

于 2008-10-08T17:04:14.700 に答える
2

getElementsByClassNameこれは、いくつかの初期の JavaScript ベースの実装を思い出させます。

indexOf正規表現を使用するよりもはるかに高速でしたが、 を使用するコードはindexOf、開発者がクラス名を (タブや改行ではなく) スペースで区切るという前提から始まりました。公平を期すために、一部の正規表現ベースの実装では\b(単語境界) を使用していましたが、これは CSS 仕様と互換性がありません (CSS ではクラス名にハイフンを使用できるため)。

indexOfIEでサポートするために使用するgetElementsByClassNameと、より高速な代替手段がなく、className プロパティの基礎となる getter/setter がタブと改行をスペースに簡単に置き換えるため、実際に違いが生じる可能性があります。

于 2008-10-09T02:54:00.783 に答える
2

むかしむかし、顕著な速度の違いがあったかもしれませんが、今はそうではありません。これは次のいずれかだと思います:

  1. (godless) The Land Before REGEX のレガシー コード。
  2. REGEX について知らない人や、それを恐れている人によって書かれています。
于 2008-10-08T16:12:06.413 に答える
1

それは本当に古いコードですか?正規表現が JavaScript で広く使用される前に作成された可能性があります。全体として、誰かが賢すぎてそのステートメントを「最適化」しようとしていたか、C のバックグラウンドから来て、正規表現に慣れていなかったようです。正規表現は使用するのにコストがかかる可能性がありますが、文字列の連結もコストがかかる可能性があり、ループ内にない場合は、理解しやすい方 (私にとっては正規表現) を使用します。

于 2008-10-08T16:03:35.417 に答える