2

1 行プログラミングに関する簡単な質問があります。最初の例:

function test(a)
{
   var b=a.toString();
   return b.replace("a","b");
}

これは非常に単純です (もちろん、この関数は役に立ちません) が、ここでの質問はもう少し複雑です: これを 1 行で行うとしたらどうなるでしょうか? 私は自分の考えを持っていますが、メモリのクリーンアップに関してこれが適切に機能することを教えてください:

function test(a)
{
   return (arguments[1]=a.toString()).doSomething().doSomethingMore(arguments[1]);
}

もちろん、これは一例ですが、考え方は簡単です。引数をローカル変数のコンテナーとして使用します。よくわかりませんが、関数が終了すると、引数も削除されますか? または、引数に新しい要素を作成すると、この要素がグローバルに定義されますか? 私のテストから、私は正しいようですが、誰かがこれを試したかどうか知りたいですか? これは安全でクリーンな解決策ですか?:) コメントありがとうございます。

以下は、1 行のスクリプトの問題に関するより現実的な問題です。

function (number,limiter)
{
return ((arguments[2] = number.toString().replace(
         new RegExp("(\\d+)(\\d{3})($|"+limiter+")"),
         '$1'+limiter+'$2$3')) == number) ?
            arguments[2] : 
            arguments.callee(arguments[2],limiter);
}

この1行の関数は、指定された文字列で処理を行い、それを返すか、同じ関数に再帰的に解析します。(他のスレッドでは、再帰なしでこれを行う方法を示していますが、これは問題ではありません)。

4

6 に答える 6

4

あなたは不必要に操作を複雑にしています。何も宣言する必要はありません。

function test(a) {
return a.toString().replace("a","b");
}

これでパフォーマンスやメモリに影響が出るはずはありません。

ただし、クロージャを使用すると、メモリの問題が発生する可能性があります。

各関数には独自の引数配列があるため、実行しているように引数配列に値を割り当てることは無意味です。スコープに関する質問に対処するために、Javascriptスコープは字句です。関数内でローカルに宣言されたものは、関数外のものに自動的にアクセスできません。

編集:arguments配列を使用することは、他のどの方法よりもクリーンで優れているわけではありません。明確にするよりも実際には悪いです。

于 2009-01-23T15:12:46.107 に答える
4

あなたの例は単純な操作を過度に複雑にしているかもしれませんが、あなたが示しているテクニックはメソッドの「連鎖」と呼ばれています。これは完全に有効な形式であり、中間結果が不要または意味がない場合にコードを読みやすくするために実際に使用できます。

これの私の現在のお気に入りの例は、素晴らしいDateJsです:

var nextTuesday = DateJs.today().next().tuesday();

var aBitLater = DateJs.now().addHours(1).addMinutes(30);

確かに、これはシンタックス シュガーであり、個別のステートメントとしてより冗長に記述できますが、メソッドの名前を慎重に付けることで、実際にはこれを英語のように読むことができます。

GC / メモリ管理はこのスタイルの影響を受けず、関数へのパラメーターは他のものと同様にクリーンアップされます。実際には、関数呼び出しが戻った後すぐにパラメーターがスコープ外になり、値を次の関数呼び出しに渡すためだけに値のローカル変数を作成する必要がないため、実際にはより安全かもしれません。

あなたの例は少し不自然かもしれませんが、意味のある場所で使用すると便利なパターンです。

于 2009-01-23T15:21:44.937 に答える
1

「デバッグは、そもそもコードを書くよりも2倍難しいです。したがって、コードをできるだけ巧妙に書くと、定義上、デバッグするほど賢くなりません。」–ブライアン・W・カーニハン

私はあなたをノックしているのではなく、熱心になりすぎないように注意しているだけです。

于 2009-01-23T15:13:45.263 に答える
0

ローカルで変数を作成することを避けようとしているのはなぜですか?そうすることで、コードがはるかに読みやすく、理解しやすくなります。実際に何かを得ているとは思いません。

変数は基本的に、作成しているオブジェクトへの単なる参照です。それらを正規変数に割り当てるか、配列に入れるかにかかわらず、クリーンアップは同じになります。メソッドが戻ると、引数配列とローカル変数の両方がスコープ外になるため、動作に違いは見られないと思います。(メソッドがapply()コマンドを介して呼び出された場合、引数配列のスコープは異なる可能性がありますが、それを確認するためのテストは行っていません)。

于 2009-01-23T15:12:22.333 に答える
0

それが「クリーンな」解決策ではないことを理解するには、それを読んでみるだけでよいと思います! 私は特に、そのような代入を連鎖させないようにします:

return (arguments[1]=a.toString()).doSomething().doSomethingMore(arguments[1]);
// is this a or a.toString()? it's not clear at a glance -------------^
于 2009-01-23T15:08:48.393 に答える
0

~~身震い~~

awkこれは、引数リストで追加の変数を宣言しない限り、関数にローカル変数を含める方法がないことを思い出させます。

ローカル変数が必要な場合は、それを実行してください。

于 2009-01-23T15:19:25.610 に答える