diff options
Diffstat (limited to 'files/ja/web/javascript/guide/functions/index.html')
-rw-r--r-- | files/ja/web/javascript/guide/functions/index.html | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/files/ja/web/javascript/guide/functions/index.html b/files/ja/web/javascript/guide/functions/index.html new file mode 100644 index 0000000000..c519b43ae3 --- /dev/null +++ b/files/ja/web/javascript/guide/functions/index.html @@ -0,0 +1,696 @@ +--- +title: 関数 +slug: Web/JavaScript/Guide/Functions +tags: + - Beginner + - Functions + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Functions +--- +<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}</div> + +<p class="summary">関数は JavaScript の基本的な構成要素のひとつです。また関数は、JavaScript の手続き ― つまり、タスクや値計算を実行する文の集まりです。関数を使うには、呼び出したいスコープ内のどこかでそれを定義する必要があります。</p> + +<p>より詳しくは <a href="/ja/docs/Web/JavaScript/Reference/Functions">JavaScript の関数に関する完全なリファレンスについての章</a>をご覧ください。</p> + +<h2 id="Defining_functions" name="Defining_functions">関数を定義する</h2> + +<h3 id="Function_declarations" name="Function_declarations">関数の宣言</h3> + +<p><strong>関数の定義</strong>(<strong>関数の宣言</strong>や{{原語併記("<strong>関数定義文</strong>","function statement")}} とも呼ばれます)は <code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function" title="function">function</a></code> キーワードと、それに続く以下の内容で構成されます。</p> + +<ul> + <li>関数の名前。</li> + <li>関数への引数のリスト。丸括弧でくくり、カンマで区切ります。</li> + <li>関数を定義する JavaScript の文。波括弧 <code>{ }</code> でくくります。</li> +</ul> + +<p>例えば、次のコードは <code>square</code> という名前の簡単な関数を定義します :</p> + +<pre class="brush: js notranslate">function square(number) { + return number * number; +} +</pre> + +<p>関数 <code>square</code> は <code>number</code> という名前の引数を 1 つとります。この関数は、引数(すなわち <code>number</code>)の 2 乗を返すように指示する 1 つの文で構成されています。<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/return" title="return"><code>return</code></a> 文は、関数が返す値を指定します。</p> + +<pre class="brush: js notranslate">return number * number; +</pre> + +<p>プリミティブなパラメータ(数値など)は<strong>値渡し</strong>で関数に渡されます。つまり、値は関数に渡されますが、関数がパラメータの値を変更しても、<strong>この変更はグローバルな値や関数の呼び出し元の値には影響を与えません</strong>。</p> + +<p>オブジェクト(すなわち非プリミティブ値、例えば {{jsxref("Array")}} オブジェクトやユーザー定義オブジェクトなど)をパラメータとして渡すと、関数がオブジェクトのプロパティを変更した場合、その変更が関数外でも有効になります。次の例をご覧ください :</p> + +<pre class="brush: js notranslate">function myFunc(theObject) { + theObject.make = 'Toyota'; +} + +var mycar = {make: 'Honda', model: 'Accord', year: 1998}; +var x, y; + +x = mycar.make; // x は "Honda" という値になる + +myFunc(mycar); +y = mycar.make; // y は "Toyota" という値になる + //(プロパティが関数で変更されている) +</pre> + +<h3 id="Function_expressions" name="Function_expressions">関数式</h3> + +<p>ここまでの関数宣言はすべて構文的な文でしたが、関数は<strong>関数式</strong>によって作成することもできます。このような関数は<strong>{{原語併記("無名","anonymous")}}</strong> にできます。名前をつけなくてもよいのです。例えば、関数 <code>square</code> は次のように定義できます :</p> + +<pre class="brush: js notranslate">const square = function(number) { return number * number } +var x = square(4) // x の値は 16 となる</pre> + +<p>ただし関数式は名前をつけることもでき、関数内で自身を参照することや、デバッガーのスタックトレースで関数を特定することに利用できます:</p> + +<pre class="brush: js notranslate">const factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) } + +console.log(factorial(3)) +</pre> + +<p>関数式は、ある関数を別の関数の引数として渡すときに便利です。次の例では <code>map</code> 関数を定義し、第 1 引数に関数を取り、第 2 引数に配列を取ります:</p> + +<pre class="brush: js notranslate">function map(f, a) { + let result = []; // 新しい配列を作成 + let i; // 変数の宣言 + for (i = 0; i != a.length; i++) + result[i] = f(a[i]); + return result; +} +</pre> + +<p>下記のコードでは、この関数は関数式で定義された関数を受け取って、2 つ目の引数で受け取った配列の各要素に対して実行しています。</p> + +<pre class="brush: js notranslate">function map(f, a) { + let result = []; // 新しい配列を作成 + let i; // 変数の宣言 + for (i = 0; i != a.length; i++) + result[i] = f(a[i]); + return result; +} +var f = function(x) { + return x * x * x; +} +let numbers = [0, 1, 2, 5, 10]; +let cube = map(f,numbers); +console.log(cube);</pre> + +<p>これは [0, 1, 8, 125, 1000] を返します。</p> + +<p>JavaScript では、条件に基づいて関数を定義することもできます。例えば次の関数の定義は、変数 <code>num</code> が 0 に等しい場合のみ <code>myFunc</code> という関数を定義します :</p> + +<pre class="brush: js notranslate">var myFunc; +if (num === 0) { + myFunc = function(theObject) { + theObject.make = 'Toyota'; + } +}</pre> + +<p>これまで説明してきた関数の定義に加えて、{{jsxref("Function")}} コンストラクタを、{{jsxref( "eval", "eval()")}} のように文字列からの関数作成に用いることができます。</p> + +<p><strong>メソッド</strong>は、オブジェクトのプロパティである関数のことです。オブジェクトとメソッドについて詳しくは、「<a href="/ja/docs/JavaScript/Guide/Working_with_Objects">オブジェクトを利用する</a>」の章をご覧ください。</p> + +<h2 id="Calling_functions" name="Calling_functions">関数を呼び出す</h2> + +<p>関数を定義しても、その関数が実行されるわけではありません。関数の定義とは、ただ単に関数に名前をつけ、その関数が呼び出されたときに何をするかを指定することです。関数の<strong>呼び出し</strong>は、実際に指定したパラメータを用いて指定された動作を実行するということです。例えば、関数 <code>square</code> を定義した場合、次のようにしてそれを呼び出すことができます:</p> + +<pre class="brush: js notranslate">square(5); +</pre> + +<p>この文は 5 という引数とともに関数を呼び出します。関数は自身の文を実行し、25 という値を返します。</p> + +<p>関数は呼び出されるスコープ内になければいけませんが、次の例のように、関数の宣言は呼び出しより後に置くことができます :</p> + +<pre class="brush: js notranslate">console.log(square(5)); +/* ... */ +function square(n) { return n * n } +</pre> + +<p>関数のスコープは自身が宣言された関数内、あるいはトップレベルで宣言されたのであればプログラム全体になります。</p> + +<div class="note"> +<p><strong>注:</strong> この動作は、上記の構文(すなわち <code>function funcName(){}</code>)を用いて関数を定義したときに限ることに注意してください。次のコードは動作しません。</p> + +<p>これは、関数の巻き上げが<em>関数式</em>ではなく<em>関数宣言</em>でしか機能しないことを意味しています。</p> + +<pre class="brush: js example-bad notranslate">console.log(square) // square は初期値が undefined の状態で巻き上げられています。 +console.log(square(5)) // Uncaught TypeError: square is not a function +const square = function(n) { + return n * n; +} +</pre> +</div> + +<p>関数の引数は、文字列や数値に限られてはいません。オブジェクト全体を関数に渡すこともできます。<code>show_props</code> 関数(「<a href="/ja/docs/JavaScript/Guide/Working_with_Objects#Objects_and_Properties">オブジェクトを利用する</a>」の章で定義)は、オブジェクトを引数にとる関数の例です。</p> + +<p>関数はその関数自身を呼び出すこともできます。例えば、ここに階乗を計算する関数を示します:</p> + +<pre class="brush: js notranslate">function factorial(n) { + if ((n === 0) || (n === 1)) + return 1; + else + return (n * factorial(n - 1)); +} +</pre> + +<p>1 から 5 までの階乗の計算は、次のようになります:</p> + +<pre class="brush: js notranslate">var a, b, c, d, e; +a = factorial(1); // a の値は 1 となる +b = factorial(2); // b の値は 2 となる +c = factorial(3); // c の値は 6 となる +d = factorial(4); // d の値は 24 となる +e = factorial(5); // e の値は 120 となる +</pre> + +<p>関数を呼び出す方法は他にもあります。関数を動的に呼び出す、関数の引数の数を変える、関数を呼び出すコンテキストを実行時に決まる特定のオブジェクトにセットするといった場合があります。</p> + +<p>関数は関数であるとともにオブジェクトでもあり、また結果としてそれらのオブジェクトはメソッドを持っています({{jsxref("Function")}} オブジェクトをご覧ください)。そうしたメソッドのひとつ、{{jsxref("Function/apply","apply()")}} メソッドを用いることでこの目的を実現できます。</p> + +<h2 id="Function_scope" name="Function_scope">関数のスコープ</h2> + +<p>関数の内部で宣言された変数は、関数の外部からアクセスすることができません。これは、変数が関数のスコープ内でのみ定義されているためです。その一方、関数は自身が定義されたスコープ内で定義されているすべての変数や関数にアクセスできます。</p> + +<p>言い換えると、グローバルスコープで定義された関数は、グローバルスコープで定義されたすべての変数にアクセスできます。ある関数の内部で宣言された関数は、自身の親となる関数内で定義されたすべての変数や、その関数がアクセス権を持つ他の変数にもアクセスできます。</p> + +<pre class="brush: js notranslate">// 以下の変数はグローバルスコープで定義 +var num1 = 20, + num2 = 3, + name = 'Chamahk'; + +// この関数はグローバルスコープで定義 +function multiply() { + return num1 * num2; +} + +multiply(); // 60 を返す + +// 入れ子になっている関数の例 +function getScore () { + var num1 = 2, + num2 = 3; + + function add() { + return name + ' scored ' + (num1 + num2); + } + + return add(); +} + +getScore(); // "Chamahk scored 5" を返す +</pre> + +<h2 id="Scope_and_the_function_stack" name="Scope_and_the_function_stack">スコープと関数スタック</h2> + +<h3 id="Recursion" name="Recursion">再帰</h3> + +<p>関数は自身を参照し、そして呼び出すことができます。関数が自身を参照する方法は 3 種類あります :</p> + +<ol> + <li>関数名</li> + <li><code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/arguments/callee">arguments.callee</a></code></li> + <li>関数を参照したスコープ内変数</li> +</ol> + +<p>例えば、以下のような関数定義を考えてみましょう :</p> + +<pre class="brush: js notranslate">var foo = function bar() { + // ここには文が来る +} +</pre> + +<p>関数本体の中で、以下のものはすべて同様の意味となります :</p> + +<ol> + <li><code>bar()</code></li> + <li><code>arguments.callee()</code></li> + <li><code>foo()</code></li> +</ol> + +<p>自身を呼び出す関数のことを<strong>再帰関数</strong>と言います。いくつかの点で、再帰はループに似ています。どちらも同じコードを何度も実行しますし、条件(無限ループを防ぐため、というより無限再帰を防ぐため)が必要です。例えば、以下のループは、:</p> + +<pre class="brush: js notranslate">var x = 0; +while (x < 10) { // "x < 10" がループ条件 + // 何らかの処理を行う + x++; +} +</pre> + +<p>再帰関数とその呼び出しとに置き換えることができます :</p> + +<pre class="brush: js notranslate">function loop(x) { + if (x >= 10) // "x >= 10" が終了条件 ("!(x < 10)" と同等) + return; + // 何らかの処理を行う + loop(x + 1); // 再帰呼出し +} +loop(0); +</pre> + +<p>一方で、単純な反復ループでは行えないアルゴリズムもあります。例えば、ツリー構造のすべてのノード(例えば <a href="/ja/docs/DOM">DOM</a> )を取得するのに、再帰を使うとより簡単に行えます :</p> + +<pre class="brush: js notranslate">function walkTree(node) { + if (node == null) // + return; + // ノードに対し処理を行う + for (var i = 0; i < node.childNodes.length; i++) { + walkTree(node.childNodes[i]); + } +} +</pre> + +<p>関数 <code>loop</code> と比較して、それぞれの再帰呼出しによってさらに多数の再帰呼出しが行われています。</p> + +<p>どんな再帰アルゴリズムも再帰でないものに書き換えることが可能です、しかしロジックはより複雑になり、データをスタックしておく必要がたびたび出てきます。実際、再帰自体がスタックを使用しています。それが関数スタックです。</p> + +<p>以下の例で、スタックとはどういったふるまいをするのか見ることができます :</p> + +<pre class="brush: js notranslate">function foo(i) { + if (i < 0) + return; + console.log('begin: ' + i); + foo(i - 1); + console.log('end: ' + i); +} +foo(3); + +// 出力: + +// begin: 3 +// begin: 2 +// begin: 1 +// begin: 0 +// end: 0 +// end: 1 +// end: 2 +// end: 3</pre> + +<h3 id="Nested_functions_and_closures" name="Nested_functions_and_closures">入れ子の関数とクロージャ</h3> + +<p>関数の中に関数を入れ子に(ネスト)することができます。入れ子になった(内部の)関数は、それを含んでいる(外部の)関数からはプライベートとなります。</p> + +<p>これにより<strong>クロージャ</strong>が作られます。クロージャとは、環境に束縛された(式によって「閉じ込められた」)変数を自由に持たせることができる式(通常は一つの関数)のことです。</p> + +<p>入れ子になった関数はクロージャなので、これはつまり、入れ子になった関数は内包する関数の引数と変数を「継承」することができるということです。別の言い方をすれば、内部の関数は外部の関数のスコープを持っているということです。</p> + +<p>まとめると :</p> + +<ul> + <li>内部の関数へは、外部関数内の文からのみアクセスできます。</li> + <li>内部の関数はクロージャを形作ります。内部関数は外部関数の引数と変数を利用でき、その一方外部関数は内部関数の引数と変数を利用できません。</li> +</ul> + +<p>以下の実例では入れ子になった関数が示されています :</p> + +<pre class="brush: js notranslate">function addSquares(a, b) { + function square(x) { + return x * x; + } + return square(a) + square(b); +} +a = addSquares(2, 3); // 13 を返す +b = addSquares(3, 4); // 25 を返す +c = addSquares(4, 5); // 41 を返す +</pre> + +<p>内部の関数はクロージャとなるので、外部の関数からクロージャを呼び出し、外部と内部両方の関数に対し引数を指定することができます :</p> + +<pre class="brush: js notranslate">function outside(x) { + function inside(y) { + return x + y; + } + return inside; +} +fn_inside = outside(3); // このように考えてください : 与えられたものに 3 を加算する関数を代入します + +result = fn_inside(5); // 8 を返す + +result1 = outside(3)(5); // 8 を返す +</pre> + +<h3 id="Preservation_of_variables" name="Preservation_of_variables">変数の保護</h3> + +<p><code>inside</code> が返されるとき、変数 <code>x</code> がどのように保護されるのかに注目してください。クロージャはそれ自身が参照しているすべてのスコープ内の引数と変数を保護することになります。それぞれの呼び出しには異なる引数が渡される可能性があるので、それぞれの <code>outside</code> の呼び出しに対し新しいクロージャが作られます。返された <code>inside</code> がもはやアクセスできなくなった時にのみメモリーは開放されます。</p> + +<p>これはその他のオブジェクトの内部で参照を保持する場合と違いはないのですが、クロージャの場合は直接参照を設定せず、また情報を取得できないので、明白さは劣ります。</p> + +<h3 id="Multiply-nested_functions" name="Multiply-nested_functions">多重入れ子関数</h3> + +<p>関数は多重に入れ子にすることができます。例えば :</p> + +<ul> + <li>関数 (<code>A</code>) は関数 (<code>B</code>) を含み、関数 (<code>B</code>) は関数 (<code>C</code>) を含んでいます。</li> + <li>ここで、関数 <code>B</code> と <code>C</code> はクロージャとなるので、<code>B</code> は <code>A</code> にアクセスでき、<code>C</code> は <code>B</code> にアクセスできます。</li> + <li>さらに、<code>C</code> は <code>A</code> にアクセスできる <code>B</code> にアクセスできるので、<code>C</code> は <code>A</code> にもアクセスできます。</li> +</ul> + +<p>このようにして、クロージャは多重スコープを導入できます。つまり関数のスコープが再帰的に包含されているのです。これを<em>スコープチェーン</em>と呼びます。(なぜ「チェーン」と呼ぶのかは後で説明します。)</p> + +<p>次の例を見てみましょう :</p> + +<pre class="brush: js notranslate">function A(x) { + function B(y) { + function C(z) { + console.log(x + y + z); + } + C(3); + } + B(2); +} +A(1); // 6 がログに出力される (1 + 2 + 3) +</pre> + +<p>この例では、関数 <code>C</code> は関数 <code>B</code> の引数 <code>y</code> と関数 <code>A</code> の引数 <code>x</code> にアクセスしています。</p> + +<p>なぜこれが可能かというと :</p> + +<ol> + <li>関数 <code>B</code> は関数 <code>A</code> に含まれたクロージャとなっています、言い換えると <code>B</code> は <code>A</code> の引数と変数にアクセスできます。</li> + <li>関数 <code>C</code> は関数 <code>B</code> に含まれたクロージャとなっています。</li> + <li>クロージャ <code>B</code> は <code>A</code> の中にあり、クロージャ <code>C</code> も <code>A</code> の中にあるので、<code>C</code> は <code>B</code>、<strong>そしてさらに</strong> <code>A</code> の引数と変数にアクセスできます。言い換えれば、<code>C</code> は <code>B</code>、<code>A</code> の順でスコープが{{原語併記("つながっている","chain")}} のです。</li> +</ol> + +<p>その一方で、逆は成り立ちません。<code>A</code> は <code>C</code> にアクセスできません、なぜなら <code>A</code> は、<code>C</code> を変数の一つとして持っている <code>B</code> の引数や変数にはアクセスできないからです。このように <code>C</code> は <code>B</code> からのみプライベートとなっています。</p> + +<h3 id="Name_conflicts" name="Name_conflicts">名前衝突</h3> + +<p>クロージャ中のスコープに同じ名前の 2 つの引数や変数がある場合、<strong>名前衝突</strong>が生じます。より内部のスコープが優先されるので、最内部にあるスコープが最優先に、一方最も外側のスコープが最も低い優先度となります。これがスコープチェーンです。チェーンの最初は最内部のスコープ、そして最後は最外部のスコープとなります。次の例を見てみましょう :</p> + +<pre class="brush: js notranslate">function outside() { + var x = 5; + function inside(x) { + return x * 2; + } + return inside; +} + +outside()(10); // 10 ではなく 20 を返す +</pre> + +<p>文 <code>return x</code> の箇所で、<code>inside</code> の引数 <code>x</code> と <code>outside</code> の変数 <code>x</code> との間に名前衝突が起きています。ここでのスコープチェーンは、{ <code>inside</code>, <code>outside</code>, グローバルオブジェクト } です。したがって <code>inside</code> の <code>x</code> が <code>outside</code> の <code>x</code> より優先され、結果 10 (<code>outside</code> の <code>x</code>)ではなく、20 (<code>inside</code> の <code>x</code>)が返されます。</p> + +<h2 id="Closures" name="Closures">クロージャ</h2> + +<p>クロージャは、JavaScript でもっとも強力な機能のひとつです。JavaScript では関数の入れ子が可能であることに加えて、内側の関数が外側の関数内で定義されたすべての変数や関数に対し(外側の関数がアクセスできる、他の変数や関数すべてにも)自由にアクセスできます。</p> + +<p>しかし、外側の関数は内側の関数内で定義された変数や関数にアクセスできません。これは、内側の関数の変数に対する一種のセキュリティ機構を提供します。</p> + +<p>また、内側の関数は外側の関数のスコープにアクセスできることから、もし内側の関数が外側の関数よりも長く生存できた場合、外側の関数内で定義された変数や関数は外側の関数よりも長く残る可能性があります。クロージャは、内側の関数が何かしらの形で外側の関数のスコープ外のどこかで使用可能になった場合に作られます。</p> + +<pre class="brush: js notranslate">var pet = function(name) { // 外側の関数は変数 "name" を定義 + var getName = function() { + return name; // 内側の関数は外側の関数の変数 "name" にアクセス可能 + } + return getName; // 内側の関数を返すことで、外側の関数に公開する +} +myPet = pet('Vivie'); + +myPet(); // "Vivie" を返す +</pre> + +<p>上記のコードより複雑なコードにすることもできます。外側の関数の内部にある変数を操作するメソッドを含む、オブジェクトを返すことができます。</p> + +<pre class="brush: js notranslate">var createPet = function(name) { + var sex; + + return { + setName: function(newName) { + name = newName; + }, + + getName: function() { + return name; + }, + + getSex: function() { + return sex; + }, + + setSex: function(newSex) { + if(typeof newSex === 'string' && (newSex.toLowerCase() === 'male' || + newSex.toLowerCase() === 'female')) { + sex = newSex; + } + } + } +} + +var pet = createPet('Vivie'); +pet.getName(); // Vivie + +pet.setName('Oliver'); +pet.setSex('male'); +pet.getSex(); // male +pet.getName(); // Oliver +</pre> + +<p>上記の例で、外側の関数の変数 <code>name</code> は内側の関数からアクセスでき、また内側の関数を通さずに内側の変数へアクセスする他の方法はありません。内側の関数の内部変数は、内側の関数の安全な保存領域として振る舞います。それらは内側の関数と連動するデータを、「永続的」かつ「安全に」保持します。関数は変数を割り当てる必要さえなく、また名前を持つ必要もありません。</p> + +<pre class="brush: js notranslate">var getCode = (function(){ + var apiCode = '0]Eal(eh&2'; // 外部の関数が変更できないようにしたいコード + + return function() { + return apiCode; + }; +})(); + +getCode(); // シークレットコードを返す +</pre> + +<div class="blockIndicator note"> +<p><strong>警告:</strong> クロージャーを使用する際に注意すべき落とし穴がいくつかあります。</p> + +取り囲まれている関数で外部スコープの変数と同じ名前の変数を定義した場合、外部スコープにある変数を再び参照する方法がなくなります。(プログラムが内部スコープを終了するまで、内部スコープ変数は外部変数を「上書き」します。) + +<pre class="example-bad brush: js notranslate">var createPet = function(name) { // 外側の関数で "name" という変数を定義します。 + return { + setName: function(name) { // 内側の関数も "name" という変数を定義します + name = name; // 外側の関数で定義した "name" へどのようにしてアクセスするのか? + } + } +} +</pre> +</div> + +<h2 id="Using_the_arguments_object" name="Using_the_arguments_object">arguments オブジェクトの使用</h2> + +<p>関数の{{原語併記("引数", "argument")}}は、配列状オブジェクトで管理されます。関数内では、次のようにして渡された引数を指定することができます :</p> + +<pre class="brush: js notranslate">arguments[i] +</pre> + +<p>ここで <code>i</code> は引数の順序を表す数で、0 から始まります。関数に渡された第 1 引数は <code>arguments[0]</code> となります。引数のトータルの数は <code>arguments.length</code> で表されます。</p> + +<p><code>arguments</code> オブジェクトを使用すると、宣言時の引数の数よりも多くの引数を用いて関数を呼び出すことができます。これによって関数に渡す引数の数が前もってわからない場合にしばしば役立ちます。<code>arguments.length</code> を使用することで、実際に関数に渡された引数の数を特定することができます。そして、<code>arguments</code> オブジェクトを使用して各引数にアクセスできます。</p> + +<p>例えば、複数の文字列を連結する関数を考えます。この関数の引数は、連結するアイテムを区切るのに用いる文字列のみです。この関数は次のように定義されています :</p> + +<pre class="brush: js notranslate">function myConcat(separator) { + var result = '', // リストを初期化する + var i; + // 引数について繰り返し + for (i = 1; i < arguments.length; i++) { + result += arguments[i] + separator; + } + return result; +} +</pre> + +<p>この関数に引数をいくつも渡すことができます。そして、各引数を文字列の "リスト" に連結します:</p> + +<pre class="brush: js notranslate">// "red, orange, blue, " を返す +myConcat(', ', 'red', 'orange', 'blue'); + +// "elephant; giraffe; lion; cheetah; " を返す +myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah'); + +// "sage. basil. oregano. pepper. parsley. " を返す +myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley'); +</pre> + +<div class="note"> +<p><strong>注記 :</strong> 変数 <code>arguments</code> は "配列状の変数" であり、配列ではありません。これは数値のインデックスと <code>length</code> プロパティがあることで、配列状となってはいます。しかし、配列操作のメソッドのすべては持っていません。</p> +</div> + +<p>さらなる情報については、JavaScript リファレンスの {{jsxref("Function")}} オブジェクトをご覧ください。</p> + +<h2 id="Function_parameters" name="Function_parameters">関数の引数</h2> + +<p>ECMAScript 2015 から、新しい形の引数が 2 つあります。それが<em>デフォルト引数</em>と<em>残余引数</em>です。</p> + +<h3 id="Default_parameters" name="Default_parameters">デフォルト引数</h3> + +<p>JavaScript では、関数の引数はデフォルトで <code>undefined</code> となります。しかし、別のデフォルト値が設定されていれば便利だという状況もあるでしょう。デフォルト引数がここで役に立ちます。</p> + +<h4 id="Without_default_parameters_pre-ECMAScript_2015" name="Without_default_parameters_pre-ECMAScript_2015">デフォルト引数なし(ECMAScript 2015 以前)</h4> + +<p>以前、デフォルト値を設定する一般的な方法は、関数の本体で引数の値をテストし、<code>undefined</code> だった場合にある値を割り当てる、というものでした。</p> + +<p>以下の例では、呼び出しの際に <code>b</code> に値が割り当てられない場合、<code>a*b</code> の評価の際に <code>b</code> の値は <code>undefined</code> となるため、<code>multiply</code> を呼び出すと <code>NaN</code> が返されます。しかしながら、例の 2 行目でこの問題を回避しています :</p> + +<pre class="brush: js notranslate">function multiply(a, b) { + b = typeof b !== 'undefined' ? b : 1; + + return a * b; +} + +multiply(5); // 5 +</pre> + +<h4 id="With_default_parameters_post-ECMAScript_2015" name="With_default_parameters_post-ECMAScript_2015">デフォルト引数あり(ECMAScript 2015 以降)</h4> + +<p><em>デフォルト引数</em>を使えば、関数本体での引数チェックはもう必要ありません。これからは、関数の最初で単純に <code>b</code> に <code>1</code> を代入することができます :</p> + +<pre class="brush: js notranslate">function multiply(a, b = 1) { + return a * b; +} + +multiply(5); // 5</pre> + +<p>詳細については、リファレンスの「<a href="/ja/docs/Web/JavaScript/Reference/Functions/Default_parameters">デフォルト引数</a>」をご覧ください。</p> + +<h3 id="Rest_parameters" name="Rest_parameters">残余引数</h3> + +<p><a href="/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数</a>の構文によって、不特定多数の引数を配列のように表すことができます。</p> + + +<p>次の例では、2 つ目から最後までの引数をまとめるのに<em>残余引数</em>を使っています。そして最初の引数を使って乗算します。(ここでは次の章で紹介するアロー関数を使っています。)</p> + +<pre class="brush: js notranslate">function multiply(multiplier, ...theArgs) { + return theArgs.map(x => multiplier * x); +} + +var arr = multiply(2, 1, 2, 3); +console.log(arr); // [2, 4, 6]</pre> + +<h2 id="Arrow_functions" name="Arrow_functions">アロー関数</h2> + +<p><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数式</a>(以前は、そして現在は正しくないが<strong>ファットアロー関数</strong>としても知られる)は関数式と比較してより短い構文を持ち、<code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code>、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/super">super</a>、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a> の値を持ちません。アロー関数は常に無名関数です。hacks.mozilla.org によるこのブログ記事もご覧ください : "<a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">ES6 In Depth: Arrow functions</a>"</p> + +<p>アロー関数の導入には 2 つの要素が絡んでいます。それは<em>短縮形の関数</em>と <code>this</code> を<em>束縛しない</em>ことです。</p> + +<h3 id="Shorter_functions" name="Shorter_functions">短縮形の関数</h3> + +<p>関数パターンによっては、短縮形の関数がうってつけです。比較してみましょう :</p> + +<pre class="brush: js notranslate">var a = [ + 'Hydrogen', + 'Helium', + 'Lithium', + 'Beryllium' +]; + +var a2 = a.map(function(s) { return s.length; }); + +console.log(a2); // logs [8, 6, 7, 9] + +var a3 = a.map(s => s.length); + +console.log(a3); // logs [8, 6, 7, 9] +</pre> + +<h3 id="No_separate_this" name="No_separate_this">別々の <code>this</code> はない</h3> + +<p>アロー関数の導入以前は、すべての新しい関数には自身の <a href="https://developer.mozilla.org/jadocs/Web/JavaScript/Reference/Operators/this">this</a> 値が定義されています(コンストラクターの場合は新しいオブジェクトに、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode">strict モード</a> の関数呼び出しの場合は undefined に、関数が「オブジェクトのメソッド」として呼び出された場合はその基底オブジェクトに、といったように)。これはオブジェクト指向プログラミングにとっては厄介です。</p> + +<pre class="brush: js notranslate">function Person() { + // この Person() コンストラクタは自身を `this` と定義します。 + this.age = 0; + + setInterval(function growUp() { + // Strict モードでない場合、この growUp() 関数は + // Person() コンストラクタによる定義とは異なり、 + // グローバルオブジェクトを `this` として定義します。 + this.age++; + }, 1000); +} + +var p = new Person();</pre> + +<p>ECMAScript 3/5 では、<code>this</code> の値をアクセス可能な別の値に割り当てることでこの問題を解決します。</p> + +<pre class="brush: js notranslate">function Person() { + var self = this; // `self` の代わりに `that` を選ぶ人もいます。 + // どちらか一方を選び、そちらだけを使うようにしましょう。 + self.age = 0; + + setInterval(function growUp() { + // このコールバックは、その値が期待通りのオブジェクトを指す + // 変数 `self` を参照している。 + self.age++; + }, 1000); +}</pre> + +<p>代わりに、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">束縛関数</a>を使って変数を束縛すれば <code>growUp()</code> 関数に適切な <code>this</code> を渡すことができます。</p> + +<p>アロー関数は自身の <code>this</code> を持ちません、つまり関数を取り囲む実行コンテキストの <code>this</code> の値が使われます。このため、下記のコードでは、<code>setInterval</code> に渡される関数内の <code>this</code> は、それを取り囲む関数の <code>this</code> と同じ値を持ちます:</p> + +<pre class="brush: js notranslate">function Person(){ + this.age = 0; + + setInterval(() => { + this.age++; // `this` は的確に person オブジェクトを参照する + }, 1000); +} + +var p = new Person();</pre> + +<h2 id="Predefined_functions" name="Predefined_functions">定義済み関数</h2> + +<p>JavaScript には、定義済みのトップレベル関数が数種類あります :</p> + +<dl> + <dt>{{jsxref("Global_Objects/eval", "eval()")}}</dt> + <dd> + <p><code><strong>eval()</strong></code> メソッドは文字列として書き表された JavaScript のコードを評価します。</p> + </dd> + <dt>{{jsxref("Global_Objects/uneval", "uneval()")}}</dt> + <dd> + <p><code><strong>uneval()</strong></code> メソッドは{{jsxref("Object","オブジェクト","","true")}}のソースコードを表す文字列を生成します。</p> + </dd> + <dt>{{jsxref("Global_Objects/isFinite", "isFinite()")}}</dt> + <dd> + <p>このグローバル関数 <code><strong>isFinite()</strong></code> は渡された値が有限数であるかを判定します。必要であれば、引数は初めに数へと変換されます。</p> + </dd> + <dt>{{jsxref("Global_Objects/isNaN", "isNaN()")}}</dt> + <dd> + <p><code><strong>isNaN()</strong></code> 関数は値が {{jsxref("Global_Objects/NaN", "NaN")}}(非数)であるかどうかを判定します。注記 : <code>isNaN</code> 関数内での強制型変換は<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/isNaN#Description">変わったルール</a>を持っています。値が非数であるかを判定するには、代わりに ECMAScript 2015 で定義された {{jsxref("Number.isNaN()")}} か、<code><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof">typeof</a></code> を使うことができます。</p> + </dd> + <dt>{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}</dt> + <dd> + <p><code><strong>parseFloat()</strong></code> 関数は引数の文字列をパースして浮動小数点数を返します。</p> + </dd> + <dt>{{jsxref("Global_Objects/parseInt", "parseInt()")}}</dt> + <dd> + <p><code><strong>parseInt()</strong></code> 関数は引数の文字列をパースして指定された基数(数学的記数法における基数)による整数を返します。</p> + </dd> + <dt>{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}</dt> + <dd> + <p><code><strong>decodeURI()</strong></code> 関数は前もって {{jsxref("Global_Objects/encodeURI", "encodeURI")}} 関数によって、あるいは同様の方法で作られた{原語併記("統一資源識別子","Uniform Resource Identifier, URI"}} をデコードします。</p> + </dd> + <dt>{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}</dt> + <dd> + <p><code><strong>decodeURIComponent()</strong></code> メソッドは前もって {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} によって、あるいは同様の方法で作られた統一資源識別子 (URI) をデコードします。</p> + </dd> + <dt>{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}</dt> + <dd> + <p><code><strong>encodeURI()</strong></code> メソッドは特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 文字から 4 文字のエスケープシーケンス(サロゲートペア文字からなる文字にのみ 4 文字のエスケープシーケンスが必要)に置き換えることで統一資源識別子 (URI) をエンコードします。</p> + </dd> + <dt>{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}</dt> + <dd> + <p><code><strong>encodeURIComponent()</strong></code> メソッドは特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 文字から 4 文字のエスケープシーケンス(サロゲートペア文字からなる文字にのみ 4 文字のエスケープシーケンスが必要)に置き換えることで統一資源識別子 (URI) コンポーネントをエンコードします。</p> + </dd> + <dt>{{jsxref("Global_Objects/escape", "escape()")}}</dt> + <dd> + <p>廃止予定の <code><strong>escape()</strong></code> メソッドはある文字列を 16 進数によるエスケープシーケンスで置換した新しい文字列を計算します。代わりに {{jsxref("Global_Objects/encodeURI", "encodeURI")}} か {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} を使用してください。</p> + </dd> + <dt>{{jsxref("Global_Objects/unescape", "unescape()")}}</dt> + <dd> + <p>廃止予定の <code><strong>unescape()</strong></code> メソッドはある文字列中の 16 進数によるエスケープシーケンスを、それが表す所定の文字に置換した新しい文字列を計算します。エスケープシーケンスは {{jsxref("Global_Objects/escape", "escape")}} といった関数によって提供されているかもしれません。<code>unescape()</code> は廃止予定なので、代わりに {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} か {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} を使用してください。</p> + </dd> +</dl> + +<p>{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}</p> |