JavaScriptモード(8):関数【概要】

5589 ワード

関数とは
関数は、1つ以上の文ブロックからなる大規模なプログラムのコードの一部です.特定のタスクを完了し、他のコードに比べて相対的な独立性を備えています.(ウィキペディア)
関数の特徴
第1クラスオブジェクト
JavaScriptの世界では、関数は一等公民であり、すべての伝統的な関数の使用方法(宣言と呼び出し)を持っているだけでなく、簡単な値のように値を割り当て、パラメータを伝達し、返すことができます.このような関数は第1級関数(First-class Function)とも呼ばれます.それだけでなく、JavaScriptの関数はクラスのコンストラクション関数として機能し、Functionクラスのインスタンスでもあります.このような多重アイデンティティはJavaScriptの関数を非常に重要にする.JavaScriptでは、関数は第1クラスオブジェクト[frist-class object]とも呼ばれます.
役割ドメインの提供
  • 関数は、実行時に動的に作成することも、プログラム実行中に
  • を作成することもできる.
  • 関数は変数に割り当てることができ、彼らの参照を他の変数にコピーすることができ、拡張することができる.また、少数の場合を除いて、関数は
  • を削除することもできる.
  • はパラメータとして他の関数に渡すことができ、他の関数から
  • を返すこともできる.
  • 関数は、独自の属性および方法
  • によって使用することができる.
    関数宣言
    JavaScript関数は、一般言語のように宣言後に使用される原則に従い、関数名にはアルファベット、数値、下線、または$しか含まれず、数値で始まることはできません.関数の一般的な宣言方法は、次の2つです.
    関数式
    直接コード:
    ```javascript
    
              //       
    
              var wr1 = function(){
    
                  // body...
    
              }
    
              //       
    
              var wr2 = function wr2(){
    
                  // body...
    
              }
    
    ```
    
    

    以上の一般化は関数式と呼ばれ、命名関数式は関数式の特殊な状況であり、通常はオプションの命名を定義する際に発生する.唯一の違いは、名前付き関数式が保持するaddがaddと見なされることである.名前を保持し続けます.これは、Firebugを使用したり、同じ関数を自分から呼び出したりするときに便利です.
    一般関数宣言
    例は次のとおりです.
    ```javascript
    
           function wr(){
    
               //body...
    
           }
    
    ```
    
    

    区別と注意
    上記の2つの関数の宣言方法には、わずかな違いがあります.
  • 最初の方法では、この関数は、割り当て前にコードにアクセスできません.つまり、この割り当ては呼び出し前に完了する必要があります.そうしないと、呼び出し時にエラーが発生します(詳細は、次の関数の昇格を参照してください).
  • 第2の方法は、宣言時に名前付き関数であり、宣言が呼び出される前、呼び出された後、実行されない場所(例えばreturn文の後、または真のブランチにはならない)にかかわらず、役割ドメイン全体で
  • にアクセスすることができる.
    関数の昇格
    ```javascript
    
           (function() {
    
                  wr1(); //wr1
    
                  function wr1() {
    
                      console.log("wr1");
    
                  }
    
                  var wr2 = function() {
    
                      console.log("wr2");
    
                  }
    
                  wr2(); //wr2
    
                 wr3(); //Uncaught TypeError: undefined is not a function
    
                 var wr3 = function() {
    
                     console.log("wr3");
    
                 };
    
          })();
    
    ```
    
    

    上記のコードでは、コンテキストのどこで宣言されているかにかかわらず、関数宣言の方法は自動的に関数定義をコンテキストの上部に昇格させますが、関数式の方法は、式の実行後にのみ正常に呼び出されます.
    関数のアップグレードは、JSの多くのバグを引き起こすことがよくあります.次の例を見てみましょう.
    ```javascript
    
           var wr = (function() {
    
               a = function() {
    
                   return 1;
    
               };
    
       
    
               function a() {
    
                   return 2;
    
               }
    
               return a;
    
          })(window);
    
          console.log(wr);
    
    ```
    
    

    このコードは、2番目のaを出力することが望ましいが、関数の昇格により、関数宣言はコンテキストフェーズに入ると変数オブジェクト(すなわち、コードの実行前)に存在するため、我々の関数式で定義されたaを出力する.
    匿名関数とネスト関数
    JavaScriptでは匿名関数(Anonymouse Function)と呼ばれる名前のない関数を宣言できます.JavaScriptでは、ネスト関数(Nested Function)と呼ばれる関数内部で関数を宣言できます.ネスト関数の役割ドメインは親関数全体です.
    JavaScriptの実行時には、グローバルな関数と変数を格納する特殊なグローバル環境(Global Object)があります.実際の開発では、いくつかのサードパーティ製のライブラリや複数のjsファイルが使用されることがよくあります.グローバルオブジェクトに重複する変数や関数宣言を誤って導入すると、コードの実行が混乱します.たとえば、2つのjsファイルを前後して導入し、それぞれ自分の関数logを内部として定義すると、2番目に導入された関数は1番目の定義を上書きし、エラーを投げ出さず、後続の実行でlog関数を呼び出すとエラーが発生する可能性があります.このとき、匿名関数を使用してjs内の論理全体をパッケージすると、このようなエラーを回避することができ、この方法はほとんどのオープンソースjsライブラリで使用されています.
    ```javascript
    
           //    
    
           (function() {
    
               function log(msg) {
    
                   console.log(msg);
    
               }
    
               // other code ...
    
           })();
    
    ```
    
    

    上記のコードは簡単な例であり、log関数の役割ドメインはこの匿名関数に制限されているが、匿名関数は外側の括弧()に含まれているため、関数式が形成され、式の値は関数であり、続いて一対の括弧は直ちにこの関数を実行し、元のコードを正常に実行させることを示す.ただし、このように宣言される関数、varによって宣言される変数などは内部的であり、匿名関数以外のコードにアクセスすることはできません.インタフェースとして関数を外部に露出する必要がある場合は、次の方法があります.
    ```javascript
    
                  var wr = (function(global) {
    
       
    
                      function log(msg) {
    
                          console.log(msg);
    
                      }
    
       
    
                      log1 = log; //   :    var          , log1      (   )
    
       
    
                      global.log2 = log; //   :          log2  ,   log  (  )
    
      
    
                     return { //   :                      ,       wr(  )
    
                         log: log
    
                     };
    
      
    
                 }(window));
    
    ```
    
    

    上記のコードに示すいくつかの方法は、1つ目は実行可能であるが、これによりグローバル変数の汚染(==埋め込みピット)を招き、異なる環境と需要に応じて、2つ目または3つ目を選択することができる.
    高次関数
    関数がパラメータや戻り値として使用される場合は高次関数と呼び、JavaScriptの関数は高次関数として使用できるのも第1クラスのオブジェクトの特徴です.次に、使い方を分析します.
    ```javascript
    
                function add(num, value) {
    
                    return num + value;
    
                }
    
       
    
                function subtract(num, value) {
    
                    return num - value;
    
                }
    
       
    
                function excute(nums, callback, value) {
    
                   var arr = [];
    
                   nums.forEach(function(val, index) {
    
                       arr.push(callback(val, value));
    
                   });
    
                   return arr;
    
               }
    
      
    
               var nums = [1, 2, 3, 4, 5];
    
               var add1 = excute(nums, add, 1);
    
               console.log(add1); //[2, 3, 4, 5, 6] 
    
               var subtract1 = excute(nums, subtract, 1);
    
               console.log(subtract1); //[0, 1, 2, 3, 4]
    
    ```
    
    

    以上のコードは、関数をパラメータとして別の関数excute呼び出しに渡す例を示しており、excute関数の実装では、callbackをブラックボックスとして扱い、パラメータを渡して戻り値を取得し、呼び出す前にcallbackの具体的な実装が不明である.18行および20行に実行される場合にのみ、callbackはaddまたはsubtractをそれぞれ表して各要素に対して+1または-1の動作を行う.
    実は高次関数は閉パッケージを結合してこそJavaScriptの柔軟性を体現しており、次のブログでは閉パッケージ(Closure)を専門に提案します.
    締めくくり
    本当にこの文章を书いて、やっと関数がまだこんなに多くの知识の点があることを発见して、ネット上で多くの牛の文章を参考にして、多くの本をも読んで、やはりしっかりしていないと感じて(多くのものは自分でもしっかりしていないので、失礼に书く勇気がありません)、次の関数の中のいくつかの点は私は専门的にいくつかの大きい塊を持ってきて、拡大します.例(JSのピット)を結合します.同様に、私の文でバグ(間違いや理解間違い)を見つけたら、指摘を歓迎します.