2012-06-26 8 views
6

私はスペンサーティッピングの優れたJavascript in Ten Minutesを再読み込みしてきた私の人生は、構文のマクロを作成するために怠惰なスコープを使用して、この例で何が起こっているのかを把握することはできませんのために:10分でJavascript:遅延スコープを示すこのコード例では何が起こっていますか?

特に
var f = function() {return $0 + $1}; 
var g = eval (f.toString().replace (/\$(\d+)/g, 
      function (_, digits) {return 'arguments[' + digits + ']'})); 
g(5,6); // => 11 (except on IE) 

を、

  1. $ 0、$ 1は関数定義によって置き換えられている - どのようその関数が評価されますでしょうか? (おそらくeval()によって、私はこれを見ていない)。
  2. 関数内の単一のアンダースコア引数の目的は何ですか?私がそれを取り出すと、コードは機能しなくなります。おそらくそれは単に場所の所有者ですが、なぜそれが必要ですか?

答えて

5

そのコードは私を怖がらせる。それはまったく使用しないでください。 (一部本当に魅力的な正当性がない限りそうを行うには、私はどの を認識していないです)また、なし「関数型プログラミング」上記のコードで示されている、おそらく除きますコールバックの使用。しかし、ちょっとしたことがあってもCは自明に行うことができます。

_は、有効な識別子(fooまたは_fooまたは$0など)です。これは、 "do not care"(値は、一致するテキスト全体の値であり、関数はRegExpの "コールバック"です)。

$0$1は(これは値「文字列に」機能のテキスト置換であることを覚えている!)はそれぞれ、arguments[0]arguments[1]に置き換えられます。

function (a,b) { return a + b } 

残り(Function.toStringeval(functionStr))「マクロ」のものをサポートするためのナンセンスです:

function() { return arguments[0] + arguments[1] } 

それとも、私が行っているだろう:それは、「マクロ」せずに手動で入力されている可能性がそれに依存する:Function -> codeString -> alteredCodeString -> Function

このコードでは、「元のまま」を発信できるの作業Function.toStringが必要です。私はいつIEがこれをサポートし始めたかはわかりませんが、IE9で動作するようです。


これは、小さな白い嘘ですが、私はこのようなアプローチを使用しているのみ場所は、フライアウトが引き込まれたとき、DOMは「途中でアンロード」することができ、サイドバーガジェットでIEを関与し、別のwindowコンテキストで関数を呼び出そうとすると、何か面倒なことが起こります。すべて-に関する厄介な状況。..

Functional JavaScript Libraryは、「マクロの魔法」はevalなしを行うことができますどのくらいを示しています。

+0

説明をありがとう(以下も)。これは、RTFMの場合です。replace()が2番目の引数として関数を取ることができなかった(または忘れていた)からです。これは実際に私の混乱でした。正規表現のマッチのためのコールバックである関数に関するあなたのコメントは、私に通知したものです。そこで、Rhinoの本の中のString.replace()のドキュメントを取り上げました。 stackOverflowに投稿する前にこれがなぜ起こっていなかったのかはっきりしませんが、もう一度感謝します。 – pgoetz

5

私はここPSTに同意するだろう、このコードはかなり怖いです。可読性が の場合は恐ろしいです。しかし、きちんとしている:

  1. fは、プレースホルダー関数の並べ替えとして定義されています。実際は マクロのようです。数値変数は をgに評価すると置き換えられます。彼らは位置的で多様な議論として行動します。
  2. g魔法が起こる場所である:fの関数定義は、文字列に を変換され、マクロ定義fの数値変数がであるなど、多くの 数値変数のためのインデックス付き引数を参照して に置き換えられますfの定義(したがって、正規表現 とreplaceを呼び出します)。最初のパラメータがreplaceの場合は、 が最初のパラメータであるため、アンダースコアが使用されただけです。

    function() { return arguments[0] + arguments[1] } 
    
  3. ので

、それはそれで、きちんとだあなたはできるだけ多くの位置の数値 引数を持つfを定義することができます:fは、本質的に に展開された後

  • 全部は、以下の、そしてeval編ですあなたが望むように:

    var f = function() { return $0 + $1 + $2 } 
    

    そしてそれは

    function() { return arguments[0] + arguments[1] + arguments[2] } 
    

    きちんとしていますが、間違いなく危険で、実用的ではなく、読みにくいです。 私はおそらくそれを使用しないでしょう。

  • 関連する問題