JavaScriptの引数にローカル変数を置き換えるというパフォーマンスヒットはありますか?

StackOverflow https://stackoverflow.com/questions/4370760

質問

ローカルのような関数を書くためのパフォーマンスヒットはありますか var ステートメントは引数に置き換えられますか?例:

function howManyMatch(arr, pattern, /*ignored:*/ i, l, total) {
  l = arr.length;
  total = 0;
  for (i = 0, i < l; i++) {
    if (pattern.test(arr[i]))
      total++;
  return total;
}

いくつかの利点:

  • ミニ型サイズが小さく:いいえ var ステートメント;
  • 少数の使用に費やすプログラマー時間が少ない vars可能な限り
  • すべてのローカルVARは1か所で定義されています

...そして短所:

  • arguments 予想外の方法で変更できます。下記参照
  • VARがローカルであることは体があまり明確ではありません
  • 何もしない議論を見るために混乱しています
  • 誰かが無意識のうちにそれらを削除した場合、あなたのコードはグローバルに書き込みます

それでも、ミニフィーターがより多くのビットを自動的に絞り出す簡単な方法かもしれません。

アップデート: これまでに言及されていない大きな欠点:nパラメーターで関数が呼び出された場合、最初のnアイテム arguments 引数リストの最初のn識別子にバインドされます(を参照してください 10.1.8の最後の弾丸)。このことを考慮:

function processStuff(/*ignored:*/i, j, k) {
    // use i/j/k to loop
    // do stuff with the arguments pseudo-array
}

上記の例では、電話した場合 processStuff(stuff1, stuff2), 、設定 ij 上書きします arguments[0]arguments[1] それぞれ。

役に立ちましたか?

解決

私はあなたがすでに知っている多くの理由でそれをしません、個人的に私は混合するという事実が好きではありません 意味的な意味 引数と変数のうち、実装レベルでは、関数が実行されるとき、それらは現在の変数オブジェクトの単なるプロパティであり、IMOは異なる意味を持っています。

さて、質問に答えてください、 パフォーマンスの影響はないと思います.

について少し話しましょう 可変インスタンス化プロセス, 、関数が実行される直前(一般的に「ホイスト」として知られています)の直前に、関数コードのために行われます。 正式なパラメーター 関数について説明されていることは、現在の変数オブジェクト(現在のスコープ)にバインドされており、関数呼び出しで渡された値で初期化されます。 undefined 供給されていない場合。

その後、すべてに属するすべての識別子 var 関数内のステートメントは現在の範囲で宣言され、で初期化されます undefined (この後に割り当てが行われることに注意してください。関数本文は実際にはまだ実行されていません)。

3番目のステップはfunctiondeclarationsであり、関数宣言のすべての識別子はローカルスコープに拘束されます。識別子が以前に宣言された場合、その値は置き換えられます。たとえば

(function (a) {
  return typeof a; // "function", not "string"

  function a () {}

})('foo');  // <-- passing a string

代わりに、単にシングルを使用することをお勧めします var 声明、関数の上部:

function howManyMatch(arr, pattern) {
  var l = arr.length,
      total = 0, i;
  for (i = 0, i < l; i++) {
    if pattern.test(arr[i]) && total++;
  return total;
}

それはあなたのコードを整理するだけでなく、JavaScriptの機能のみの範囲との「巻き上げ」の性質による不要な結果を防ぐのに役立ちます var, 、一部のツール jslintが励まします これもまた。

他のヒント

いいえ、これをしないでください。それは混乱していて不必要です。そして、私はあなたの「利点」のリストが非常に具体的であると思います - そこにあるすべてのアイテムはあります 非常に薄いです 得られた実際の利益について。

必要な場合は、を使用してください コンマオペレーター すべての変数を関数の頭にある単一のステートメントで宣言します(とにかくこの場所に巻き上げられます。

function howManyMatch(arr, pattern) {
  var i, l, total;
  // rest
}

または、一度のステップですべてを宣言/定義することもできます

function howManyMatch(arr, pattern) {
  var l = arr.length, total = 0, i = 0;
  // rest
}

ここでは、読みやすさと保守性のアウトウェイトファイルズサイズとマイクロプチミズ化と思います。そうです 多くの あるコードを読みやすい var キーワード。それに加えて、1つ var スコープごとのステートメントは十分でなければなりません(とにかくJavaScriptがそれらを掲げます)。 全て ローカル変数が利用可能です どこにでも ローカルスコープで(注文に関係なく宣言されています)。したがって、すべてのローカル変数は、最良の読みやすさを得るために(ローカルスコープの先頭)同じ位置で宣言する必要があります。これらの4つのバイト var ステートメントは、ユーザーにできるようにすることで、可能なバグを導入する価値がありません ローカル変数の初期値を設定します 追加のパラメーターでその関数を呼び出すことにより。カプセル化を破ります(あなた できる これを正しく理解しますが、省略することで保存するよりも多くのバイトになります var)。それに加えて、それはあなたのコードを読み込もうとしている人と本当に混乱しています。

あなたが与える同じ利点は、ただ削除するだけで達成できます var キーワード:

function howManyMatch(arr, pattern) {
  l = arr.length;
  total = 0;
  for (i = 0; i < l; i++) {
    if pattern.test(arr[i]) && total++;
  return total;
}

明示的に書く必要はありません var キーワード、この場合のすべての変数を値で定義しているので( l = arr.length, total = 0, i = 0 ).

ちなみに、変数を関数引数として定義することにより、変数を事前定義できないことに注意してください。たとえば、これは不可能です。

function howManyMatch(arr, pattern, i=0, l, total = 0){ ... }

したがって、不利な点が残っているため、コードを削除するソリューションは非常に役立つとは思いません。)


編集

変数を定義せずに定義するという事実については考えていませんでした var キーワードはそれらをグローバルに変えます。それはあなたがまったく欲しくないものかもしれません...

しかし、問題についてもう一度考えているように、関数引数の変数を定義したい理由はわかりません。あなたがその方法に与えるすべての利点は、基本的にこの例にも当てはまります。

function howManyMatch(arr, pattern) {
  var l = arr.length, total = 0, i=0;
  for (; i < l; i++) {
    if pattern.test(arr[i]) && total++;
  return total;
}

そして、この例はさらに短くなっています。

「テスト駆動型JavaScript Development」のチスチャンヨハンセン(2011)は次のように述べています。オブジェクトはオーバーヘッドを誘発し、ブラウザがそれを使用しない関数を最適化することを示します。」

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top