2011-01-15 10 views
1

私はJavaScriptの中で、ネストされたリテラルと呼ばれるパターンを見つけました。自己呼び出し関数リテラルの引数として、自己呼び出し関数リテラルを持つことができるため、これは機能します。JavaScriptのネストされたリテラル、良い考えですか?

自己呼び出し関数リテラルはそうように、すぐにそれ自体を評価する関数である:

(function(arg1, arg2) { return arg1 + arg2; }) (1, 2); 

これは、自己呼び出し関数リテラルを使用することの1つの利点は、ある

3; 

を書き込むと等価ですそのコードは厳密にトップダウンであり、理解しやすくなっています。あなたは、自己の呼び出し機能リテラルとしてのdocument.write()の引数を認識仮定し

document.write(
    (function(
     factorial, 
     square 
    ) { 
     return factorial(square(3)); 
    } (
     function f(x) { 
      if (x <= 1) return 1; 
      else return x * f(x - 1); 
     }, 
     function f(x) { 
      return x*x; 
     } 
    )) 
); 

を考えてみましょう、あなたはこのプログラムはに3の四角の階乗を書き込みことを理解することは非常にスマートである必要はありません階乗関数と平方関数がどのように実装されているかを理解することができます。プログラムは直感的に "文書の中で、階乗が正方形である3の正方形の階乗を書いてください..."と読みます。

さらに、自己呼び出す関数リテラルの引数の1つを関数リテラルそのものにすることを止めることから何もありません。たとえば:

(function(arg1, arg2) { return arg1 + arg2 }) (
    1, 
    (function(arg1, arg2) { return arg1 + arg2 })(2, 3) 
); 

これはあなたが理解することは非常に簡単です、非常に複雑なリテラルを加えることができ、上に行くことができ

6; 

このネスティングを書くことと等価です。私は何をするかは明白だと思う

document.write(
    /* text = */ (
     (function(
      title, 
      section1, 
      section2, 
      section3 
     ) { 
      return ('<h3>' + title + '</h3>' + 
        section1 + 
        section2 + 
        section3 
        ); 
     } (
      /* title = */ (
       'Nested Literals in JavaScript' 
      ), 
      /* section1 = */ (
       (function(
        title_section1, 
        paragraph1_section1, 
        paragraph2_section1 
       ) { 
        return ('<h4>' + title_section1 + '</h4>' + 
          '<p>' + paragraph1_section1 + '</p>' + 
          '<p>' + paragraph2_section1 + '</p>' 
          ); 
       } (
        /* title_section1 = */ (
         'Nested Literals' 
        ), 
        /* paragraph1_section1 = */ (
         "JavaScript allows nested literals through its self invocating function literals. This is because self invocating function literals take literals as arguments. Therefore, a self invocating function literal can take an argument that is a self invocating function literal that can take an argument that is ... ." 
        ), 
        /* paragraph2_section1 = */ (
         "This is cool! for it allows arbitrarily complex literals. This program consists out of a single call to document.write(), its argument being relatively complex." 
        ) 
       )) 
      ), 
      /* section2 = */ (
       (function(
        title_section2, 
        paragraph1_section2, 
        paragraph2_section2, 
        paragraph3_section2 
       ) { 
        return ('<h4>' + title_section2 + '</h4>' + 
          '<p>' + paragraph1_section2 + '</p>' + 
          '<p>' + paragraph2_section2 + '</p>' + 
          '<p>' + paragraph3_section2 + '</p>' 
          ); 
       } (
        /* title_section2 = */ (
         'Top-Down Coding' 
        ), 
        /* paragraph1_section2 = */ (
         "Using nested literals, your code can become very readable. Reading the code from top to bottom you will get to understand the structure top-down, which is how we (at least I) like it." 
        ), 
        /* paragraph2_section2 = */ (
         "This code is an example of this. What it does is probably obvious on your first read. If not, then it is probably because you are not familiar enough with self invocating function literals, yet." 
        ), 
        /* paragraph3_section2 = */ (
         "And not only does it makes programs easy to read, it makes them easy to write." 
        ) 
       )) 
      ), 
      /* section3 = */ (
       (function(
        title_section3, 
        paragraph1_section3, 
        paragraph2_section3, 
        paragraph3_section3 
       ) { 
        return ('<h4>' + title_section3 + '</h4>' + 
          '<p>' + paragraph1_section3 + '</p>' + 
          '<p>' + paragraph2_section3 + '</p>' + 
          '<p>' + paragraph3_section3 + '</p>' 
          ); 
       } (
        /* title_section3 = */ (
         'Local Variables Only' 
        ), 
        /* paragraph1_section3 = */ (
         "Because everything is literal, or anonymous, no assignments are made. This keeps the global scope completely clean." 
        ), 
        /* paragraph2_section3 = */ (
         "Also, arguments to a self invocating function literal are outside the scope of the body of the self invocating function literal. This makes their scopes completely separated. Even though their behaviour is nested, their scopes are not." 
        ), 
        /* paragraph3_section3 = */ (
         "This puts nested literals in contrast to nested functions, which allow their behaviour to get tangled up with the variables of the function in which they are nested." 
        ) 
       )) 
      ) 
     )) 
    ) 
); 

:最終的なプログラムを考えてみましょう。あなたはあなたのアドレスバーのテキストフィールドをクリックし、 'javascript:'と打ち込んで、上記のソースコードを貼り付けて、Enterキーを押して実行することができます。

私が確信しているのは、ネストされたリテラルの使用効率がどの程度であるかです。もしあなたがこれを極限までおこなうのであれば、どんなトラブルにも遭遇するのではないかと思います。誰もが知っているのだろうかと思っています。

とにかく、私はこれを共有したいと思っていたかもしれません。

よろしく、ピーター・ヤン

+2

ほとんどすべての現代のJavascriptフレームワークは、このようなものです。また、技術的には、関数は「自己呼び出し」ではありません。それらを「即座に呼び出された無名関数」と呼ぶ方が正確です。 Underscore.jsとFunctional.jsライブラリをチェックして、Javascriptで機能的なスタイルでコーディングする素晴らしい例を探してください。 – Pointy

+4

私は「分かりやすい」という意見に同意しない。私はそれを読んで理解することができませんが、私はあなたにそれを書いて頂きたいと思います。 – goat

+1

あなたの質問は? – meouw

答えて

3

私が言うすべてがある:あなたのコードが読み取り可能であることを確認してください。このようなことをやってはいけません。それはあなたが涼しいからです。です。あなたのコードを読みやすくするなら、それをしてください。それはときどきありますが、時には間違いないと思います。

+0

はい、私は可読性が高いことに同意します。ネストされたリテラルは、上から下に読むことで、リテラル構造をトップダウンで読むことができるので、非常に読みやすいようにすることができます。リテラルの使用に慣れていないと、それは非常に奇妙で複雑に見えると私は想像することができます。 –

+0

しかし、あなたが単に木を見ているとわかったら、最後のプログラムは理解しやすく、変更するのが簡単だと言います。 –

1

私はそれは良い考えではありません、なぜ

  • あなたのコードが遅くなり、少なくとも二つの主要な理由を見ることができます - あなたはJavaScriptで関数呼び出しを行うたびに、新しいコールスタックは、他のものの中で初期化する必要があります関数が何をするのが簡単で一度だけ起こる必要があるのであれば、大規模なオーバーヘッドになります。なぜなら、通常のループはjQueryなどの便利なメソッドを使用するよりもずっと高速です。

  • 同じことを2回以上行う必要がある場合は、関数を使用しますが、名前を付けて参照することで、コードを無限に維持しやすくなります。名前付き関数は、プロファイル可能な - 匿名関数で散らばっている多くのJavaScriptをプロファイルしようとすると、片手で拍手が降るようなものです。

+0

私はそれを読むと、片手で拍手するような面白いことが分かりました。 –

+0

私は参照してください。プロファイリングの引数は良いものです。 私は、同じコードを再利用できるように、いくつかの場所で関数を使用することが常に見えるようにする必要があることに同意します。まったく同じ機能を持つ2つのコードを持つこと、あるいはオーバーラップする機能性を持つことにはほとんど意味がありません。 –

関連する問題