関数

関数は、関数に渡される引数に基づいて値を計算して返すなど、一連の関連タスクを実行するために使用される、モジュール式で再利用可能なステートメントのブロックです。すべての非プリミティブ値と同様に、関数はオブジェクトです。これらは一意のオブジェクトであり、コードを実行するために呼び出し引数の形式でデータを渡して、値をreturnことができます。

関数は「ファースト クラス」オブジェクトとみなされます。つまり、関数は独自の動作にもかかわらず、他の JavaScript オブジェクトとすべて同じコンテキストで使用できます。たとえば、関数は変数に代入したり、引数として他の関数に渡したり、他の関数から返したりすることができます。

function myFunction() {
   console.log( "This is my function." );
};

オブジェクトのプロパティとして定義される関数は、通常「メソッド」と呼ばれます。var を使用して宣言された変数と同様に、包含関数の外部で行われた関数宣言は、メソッドとしてグローバル オブジェクトに追加されます。

関数宣言

関数宣言(「関数ステートメント」または「関数定義」とも呼ばれます)は、含まれるスコープ内の別の場所で呼び出すことができる名前付き関数を作成します。関数宣言は、function キーワードの後に識別子、かっこで囲まれたカンマ区切りパラメータのリスト、「関数本体」と呼ばれるブロック ステートメントで構成されます。セミコロンで終わらない関数宣言はよくあります。関数宣言はステートメントであるため、末尾のセミコロンは ASI によって推測できます。

function myFunction() {
   console.log( "This is my function." );
};

myFunction();
> "This is my function."

JavaScript の初期の設計上の決定からのホールドオーバーとして、関数宣言には、var で宣言された変数と同じ従来のホイスティング動作が適用されます。つまり、関数宣言はスコープの一番上にホイスティングされ、スコープが厳格モードで管理されているかどうかにかかわらず、宣言の前に呼び出すことができます。

"use strict";
{
    myFunction();
    function myFunction() {
        console.log( "This is my function." );
    };
}
> "This is my function."

厳格モードの外部では、関数宣言は JavaScript の従来のスコープ動作を使用します。つまり、関数宣言のスコープは、その最も近い包含関数に設定されます。

function myFunction() {
    function myNestedFunction() {
        console.log( "This is my nested function." );
    }
    myNestedFunction();
};

myFunction();
> "This is my nested function."

myNestedFunction();
>Uncaught ReferenceError: myNestedFunction is not defined

厳格モードでは、let または const を使用して宣言された変数と同様に、関数宣言のスコープは最も近いブロックに限定されます。

"use strict";
{
    function myFunction() {
        console.log( "This is my function." );
    };
}

myFunction();
> Uncaught ReferenceError: myFunction is not defined

関数呼び出し

変数と同様に、関数を宣言する際に使用される識別子は、値のシンボリック名として機能します。識別子のみで関数を参照すると、関数オブジェクトのみが返され、含まれる関数は実行されません。

function myFunction() {
   console.log( "This is my function." );
};

myFunction;
> myFunction() {
   console.log( "This is my function." );
}

関数本体内のコードを実行するには、関数名の後にかっこのペアを続けて入力し、関数を呼び出し(または呼び出し)します。

function myFunction() {
    console.log( "My function has been executed." );
}

myFunction();
> "My function has been executed."

関数定義のパラメータは、関数の呼び出し時に関数本体に渡すことができる値のプレースホルダ変数として機能します。関数の呼び出し時のかっこ内の値は「引数」です(ドキュメントによっては、引数とパラメータの両方を記述するために「引数」を使用していることがあります)。

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

期待される引数が省略された場合、結果のパラメータには undefined 値が含まれます。パラメータは関数本体に対して宣言されますが、値で初期化されないためです。

function myFunction( myParameter ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction();
> "The value is: undefined."

デフォルトのパラメータ値を設定するには、変数を初期化するのと同じ方法で、代入演算子(=)の後に値を続けます。後でその関数に引数を指定すると、その新しい値がデフォルト値をオーバーライドします。

function myFunction( myParameter = "omitted" ) {
   console.log( `The value is: ${ myParameter }.` );
};

myFunction( "this string" );
> "The value is: this string."

myFunction();
> "The value is: omitted."

矢印以外の関数の本文は、関数定義でパラメータが指定されているかどうかに関係なく、引数として渡された値を含むゼロ インデックスの配列のような arguments オブジェクトにアクセスできます。

function myFunction() {
   console.log( arguments );
};

myFunction( 3, true, "My string" );
> Arguments { 0: 3, 1: true, 2: "My string", … }

可変長関数

arguments オブジェクトを使用すると、可変数の引数を受け入れることができる基本的な変数関数を作成できます。

function myFunction() {
    let result = "";
    for (let i = 0; i < arguments.length; i++) {
        result += arguments[i] + " - ";
    }
    console.log( result );
};

myFunction( "My first string", "My second string", "my third string" );\
> "My first string - My second string - my third string - "

しかし、可変長関数に対するこのアプローチは、最新の JavaScript 開発ではほとんど使用されません。より新しく読みやすい rest パラメータ構文を使用するのが一般的です。この構文では、明示的に指定された引数以外の引数を含む配列として初期化される名前付きパラメータが作成されます。

function myFunction( mySeparator, ...myStrings ) {
  console.log( myStrings.join( mySeparator ) );
};

myFunction( " - ", "My first string", "My second string", "my third string" );
> "My first string - My second string - my third string"

parameter バインディングとは異なり、アロー関数パラメータでは残りのパラメータ構文が想定どおりに機能します。

function myOuterFunction() {
    let myInnerArrowFunction = ( ...myParams ) => {
        console.log( myParams[ 0 ] );
    }
    myInnerArrowFunction( true );
};

myOuterFunction( false );
> true

let myArrowFunction = ( ...myParams ) => {
    console.log( myParams[ 0 ] );
};

myArrowFunction( true );
> true`
``