Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年7月.
* Some parts of this feature may have varying levels of support.
一般的に言うと、関数とは外部 (再帰の場合は内部) から呼び出すことのできる「サブプログラム」です。プログラムそのもののように、関数は関数本体 (function body) と呼ばれる連続した文で構成されます。関数には引数として値を渡すことができ、関数は値を返すことができます。
JavaScript で、関数は第一級オブジェクトです。関数は他の関数に渡したり、関数から返したり、変数やプロパティに代入したりできるからです。また、それ以外のオブジェクトと同様にプロパティやメソッドを持つこともできます。他のオブジェクトと異なる点は、関数は呼び出せるということです。
より詳細な例や解説については、JavaScript の関数のガイドを参照してください。
関数値は通常、Function のインスタンスです。 Function オブジェクトのプロパティとメソッドに関する情報については、 Function を参照してください。呼び出し可能な値であるため、typeof は "object" ではなく "function" を返します。
メモ: 呼び出し可能な値のすべてが instanceof Function であるとは限りません。例えば、Function.prototype オブジェクトは呼び出し可能ですが、Function のインスタンスではありません。また、関数のプロトタイプチェーンを手動で設定して、Function.prototype からの継承をやめることもできます。ただし、そのようなケースは非常に稀です。
既定では、関数の実行が return 文で終わらない場合、または return キーワードの後に式がない場合、返値は undefined となります。 return 文を使用すると、関数から任意の値を返すことができます。 1 回の関数呼び出しで返せる値は 1 つだけですが、オブジェクトや配列を返して結果を構造分解することで、複数の値を返す効果を模倣することができます。
メモ: new で呼び出されるコンストラクターは、返値を決定するための一連のロジックが異なります。
仮引数 (parameter) と実引数 (argument)があり、意味が若干異なりますが、 MDN web docs では多くの場合同じ意味で使用されています。簡単に言うと、
この例では、 num 変数は関数の「仮引数」 (parameter) と呼ばれ、関数定義の括弧で囲まれたリスト内で宣言されます。関数は num 仮引数が数値であることを期待しています。ただし、 JavaScript では実行時検証コードを書かない限り、これを強制することはできません。 formatNumber(2) の呼び出しにおいて、数値 2 は関数の「実引数」 (argument) です。これは関数呼び出し時に実際に渡される値です。 実引数の値は、関数本体内で対応する引数名または arguments オブジェクトを通じてアクセスできます。
引数は常に値渡しであり、決して参照渡しではありません。これは、関数が引数に再代入を行っても、関数外では値が変更されないということです。より正確には、オブジェクト引数は共有渡しです。つまり、オブジェクトのプロパティが変更される場合、その変更は関数外にも影響するということです。例えば、
this キーワードは、関数がアクセスされたオブジェクトを参照します。現在実行中の関数を参照するのではなく、関数本体内であっても関数値は名前で参照する必要があります。
大まかに言えば、 JavaScript には 4 種類の関数があります。
どの種類の関数でも、それを定義する方法は複数あります。
宣言function, function*, async function, async function*
式function, function*, async function, async function*
コンストラクターFunction(), GeneratorFunction(), AsyncFunction(), AsyncGeneratorFunction()
さらに、アロー関数 と メソッド を定義するための特別な構文があり、これらはその用法に明確な意味づけを提供します。クラスは概念的には関数ではありません(new なしで呼び出されるとエラーが発生するため)。しかし、それらは Function.prototype を継承し、 typeof MyClass === "function" となります。
すべての構文はおおむね同じことをしますが、微妙な動作の違いがいくつかあります。
function 式では、関数名と関数が代入される変数には違いがあります。関数名は変更できませんが、関数が代入される変数は再代入できます。関数名は、関数が代入される変数とは異なる名前を付けることが可能です。両者は、互いに関連のありません。関数名は関数本体内でのみ使用できます。関数本体外で使用しようとするとエラーが発生します(または、同じ名前が別の場所で宣言されている場合は別の値が取得されます)。 例えば、
一方、関数が代入される変数は、そのスコープによってのみ制限されます。このスコープには、関数が宣言されたスコープを含むことが保証されています。
関数宣言は、関数名と同じ名前の変数も作成します。したがって、関数式で定義されたものとは異なり、関数宣言で定義された関数は、自身の本体内だけでなく、定義されたスコープ内でもその名前でアクセスできます。
new Function で定義された関数は、そのソースが動的にアセンブルされます。これはシリアライズ時に確認できます。例えば、console.log(new Function().toString()) は次のような結果になります。
これは関数をコンパイルするために実際に使用されるソースです。ただし、 Function() コンストラクターは anonymous という名前の関数を生成しますが、この名前は本体スコープには追加されません。本体は常にグローバル変数にしかアクセスできません。例えば、次のものはエラーになります。
関数式または関数宣言によって定義された関数は、現在のスコープを継承します。つまり、その関数はクロージャを形成します。一方、 Function コンストラクターによって定義された関数は、グローバルスコープ(すべての関数が継承する)以外のスコープを継承しません。
関数式や関数宣言で定義された関数は一度だけ構文解析されますが、 Function コンストラクターで定義された関数は、コンストラクターが呼び出されるたびに渡された文字列を毎回構文解析します。関数式はそれぞれクロージャを生成しますが、関数本体は再解析されないため、関数式は new Function(...) よりも高速です。したがって、可能な限り Function コンストラクターの使用は避けるべきです。
関数宣言は、式コンテキスト内で現れた場合、意図せず関数式に変換されることがあります。
一方、関数式は関数宣言に変換されることもあります。式文は function や async function キーワードで始めることはできません。これは IIFE(即時実行関数式)を実装する際によく見られる間違いです。
代わりに、式文を別の方法で始まるようにし、 function キーワードで確実に関数式が始まるようにします。一般的な選択肢には、グループ化や void の使用があります。
関数のそれぞれの引数は、ローカルスコープ内でアクセスできる単純な識別子です。
特別な引数の構文が 3 種類あります。
上記の単純でない引数構文のいずれかが使用されている場合、いくつかの影響があります。
arguments オブジェクトを使用すると、関数内部で関数の実引数を参照することができます。
arguments現在実行中の関数に渡された引数を格納する配列風オブジェクト。
arguments.callee現在実行中の関数。
arguments.length:関数に渡された引数の数。
標準の組み込みオブジェクトや ユーザー定義オブジェクトには、追加のプロパティに対応しているものなら、いずれにもアクセサープロパティを定義できます。オブジェクトリテラルやクラス内で、特別な構文を使用してアクセサープロパティのゲッターとセッターを定義することができます。
getオブジェクトのプロパティを、そのプロパティが検索されたときに呼び出される関数に束縛します。
setあるオブジェクトのプロパティを、そのプロパティに代入しようとしたときに呼び出される関数に結びつけます。
なお、これらの構文はオブジェクトのメソッドではなく、プロパティを生成します。ゲッター関数やセッター関数自体は、Object.getOwnPropertyDescriptor() などのリフレクション API を使用してのみアクセスできます。
厳格モードでは、ブロック内の関数はそのブロックに新しいスコープを形成します。 ES2015 より前では、ブロックレベル関数は厳格モードでは禁止されています。
一言で言えば、使わないでください。
厳格モードのコード以外では、ブロック内の関数宣言は奇妙な動作をします。次の例を見てください。
厳格モードにおけるこの意味づけは明確に指定されています。 zero は常に if ブロックのスコープ内でのみ存在します。 shouldDefineZero が false の場合、ブロックは決して実行されないため、 zero は定義すべきでは決してありません。しかし、過去にはこれは未指定のままにされていたため、厳格モード以外ではブラウザーによって実装が異なっていました。より詳細な情報については、function宣言のリファレンスを参照してください。
条件付きで関数を定義するより安全な方法は、変数に関数式を代入することです。
次の関数は、数値を先頭にゼロを付けて書式化した文字列で返します。
次の文で padZeros 関数を呼び出します。
typeof 演算子を使うと、関数が存在するかどうかを確かめることができます。次の例では、window オブジェクトが noFunc という関数のプロパティを持つかどうかを確かめるためのテストが行われます。もし持っていたら、それが使われます。そうでなければ、他の行動が取られます。
if のテストの中で、noFunc への参照が使われているのに注目してください。関数名の後に括弧 "()" がないので、実際の関数は呼び出されません。
| ECMAScript® 2027 Language Specification # sec-function-definitions |
Enable JavaScript to view this browser compatibility table.
This page was last modified on 2025年9月18日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.