1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
|
---
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">関数の定義</h2>
<h3 id="Function_declarations">関数宣言</h3>
<p><strong>関数定義</strong> (<strong>関数宣言</strong>や<strong>関数定義文</strong> とも呼ばれます) は <a href="/ja/docs/Web/JavaScript/Reference/Statements/function"><code>function</code></a> キーワードと、それに続く以下の内容で構成されます。</p>
<ul>
<li>関数の名前。</li>
<li>関数への引数のリスト。丸括弧でくくり、カンマで区切ります。</li>
<li>関数を定義する JavaScript の文。波括弧 <code>{...}</code> でくくります。</li>
</ul>
<p>例えば、次のコードは <code>square</code> という名前の簡単な関数を定義します。</p>
<pre class="brush: js">function square(number) {
return number * number;
}
</pre>
<p>関数 <code>square</code> は <code>number</code> という名前の引数を 1 つとります。この関数は、引数 (すなわち <code>number</code>) の 2 乗を返すように指示する 1 つの文で構成されています。<a href="/ja/docs/Web/JavaScript/Reference/Statements/return"><code>return</code></a> 文は、関数が返す値を指定します。</p>
<pre class="brush: js">return number * number;
</pre>
<p>プリミティブな引数 (数値など) は<strong>値渡し</strong>で関数に渡されます。つまり、値は関数に渡されますが、関数が引数の値を変更しても、<strong>この変更はグローバルな値や関数の呼び出し元の値には影響を与えません</strong>。</p>
<p>オブジェクト (すなわち非プリミティブ値、例えば {{jsxref("Array")}} オブジェクトやユーザー定義オブジェクトなど) を引数として渡すと、関数がオブジェクトのプロパティを変更した場合、その変更が関数外でも有効になります。次の例をご覧ください。</p>
<pre class="brush: js">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">関数式</h3>
<p>ここまでの関数宣言はすべて構文的な文でしたが、関数は<a href="/ja/docs/Web/JavaScript/Reference/Operators/function">関数式</a>によって作成することもできます。</p>
<p>このような関数は<strong>無名</strong> (anonymous) にすることができます。名前をつけなくてもよいのです。例えば、関数 <code>square</code> は次のように定義することができます。</p>
<pre class="brush: js">const square = function(number) { return number * number }
var x = square(4) // x の値は 16 となる</pre>
<p>ただし、関数式には名前を指定することもできます。名前を指定することで、関数が自分自身を参照することができ、また、デバッガーのスタックトレースで関数を特定しやすくなります。</p>
<pre class="brush: js">const factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) }
console.log(factorial(3))
</pre>
<p>関数式は、ある関数を別の関数の引数として渡すときに便利です。次の例では、第 1 引数に関数を、第 2 引数に配列を受け取るべき <code>map</code> 関数を示しています。</p>
<pre class="brush: js">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">function map(f, a) {
let result = []; // 新しい配列を作成
let i; // 変数の宣言
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
const f = function(x) {
return x * x * x;
}
let numbers = [0, 1, 2, 5, 10];
let cube = map(f,numbers);
console.log(cube);</pre>
<p>これは <code>[0, 1, 8, 125, 1000]</code> を返します。</p>
<p>JavaScript では、条件に基づいて関数を定義することもできます。例えば次の関数の定義は、 <code>myFunc</code> という関数を、変数 <code>num</code> が <code>0</code> に等しい場合のみ定義します。</p>
<pre class="brush: js">var myFunc;
if (num === 0) {
myFunc = function(theObject) {
theObject.make = 'Toyota';
}
}</pre>
<p>これまで説明してきた関数の定義に加えて、{{jsxref("Function")}} コンストラクターを、{{jsxref("Global_Objects/eval", "eval()")}} のような文字列からの関数作成に用いることができます。</p>
<p><strong>メソッド</strong>は、オブジェクトのプロパティである関数のことです。オブジェクトとメソッドについて詳しくは、「<a href="/ja/docs/Web/JavaScript/Guide/Working_with_Objects">オブジェクトを利用する</a>」の章をご覧ください。</p>
<h2 id="Calling_functions">関数の呼び出し</h2>
<p>関数を<em>定義</em>しても、その関数が<em>実行</em>されるわけではありません。関数の定義とは、ただ単に関数に名前をつけ、その関数が呼び出されたときに何をするかを指定することです。</p>
<p>関数の<strong>呼び出し</strong>は、指定した引数を用いて実際に指定された動作を実行します。例えば、 <code>square</code> という関数を定義した場合、次のようにして呼び出すことができます。</p>
<pre class="brush: js">square(5);
</pre>
<p>この文は <code>5</code> という引数とともに関数を呼び出します。関数は自身の文を実行し、 <code>25</code> という値を返します。</p>
<p>関数を呼び出すときは<em>スコープ内</em>になければいけませんが、次の例のように、関数の宣言を巻き上げる (呼び出しより後に置く) ことができます。</p>
<pre class="brush: js">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">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/Web/JavaScript/Guide/Working_with_Objects#objects_and_properties">オブジェクトを利用する</a>の章で定義) は、オブジェクトを引数にとる関数の例です。</p>
<p>関数はその関数自身を呼び出すこともできます。例えば、ここに階乗を計算する関数を示します。</p>
<pre class="brush: js">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">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><em>関数はそれ自体がオブジェクト</em>です。 — そして、それらのオブジェクトはメソッドを持っています。 ({{jsxref("Function")}} オブジェクトを参照してください。) そのうちのひとつ、 {{jsxref("Function.apply", "apply()")}} メソッドを使って、この目的を達成することができます。</p>
<h2 id="Function_scope">関数のスコープ</h2>
<p>関数の内部で宣言された変数は、関数の外部からアクセスすることができません。これは、変数が関数のスコープ内でのみ定義されているためです。その一方、関数は自身が定義されたスコープ内で定義されているすべての変数や関数にアクセスできます。</p>
<p>言い換えると、グローバルスコープで定義された関数は、グローバルスコープで定義されたすべての変数にアクセスできます。ある関数の内部で宣言された関数は、自身の親となる関数内で定義されたすべての変数や、その関数がアクセス権を持つ他の変数にもアクセスできます。</p>
<pre class="brush: js">// 以下の変数はグローバルスコープで定義
var num1 = 20,
num2 = 3,
name = 'Chamakh';
// この関数はグローバルスコープで定義
function multiply() {
return num1 * num2;
}
multiply(); // 60 を返す
// 入れ子になっている関数の例
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
}
getScore(); // "Chamakh scored 5" を返す
</pre>
<h2 id="Scope_and_the_function_stack">スコープと関数スタック</h2>
<h3 id="Recursion">再帰</h3>
<p>関数は自身を参照し、呼び出すことができます。関数が自身を参照する方法は 3 種類あります。</p>
<ol>
<li>関数名</li>
<li><code><a href="/ja/docs/Web/JavaScript/Reference/Functions/arguments/callee">arguments.callee</a></code></li>
<li>関数を参照しているスコープ内の変数</li>
</ol>
<p>例えば、以下のような関数定義を考えてみましょう。</p>
<pre class="brush: js">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>
<p>例えば、以下のループは・・・</p>
<pre class="brush: js">var x = 0;
while (x < 10) { // "x < 10" がループ条件
// 何らかの処理を行う
x++;
}
</pre>
<p>再帰関数の宣言とその呼び出しとに置き換えることができます。</p>
<pre class="brush: js">function loop(x) {
if (x >= 10) // "x >= 10" が終了条件 ("!(x < 10)" と同等)
return;
// 何らかの処理を行う
loop(x + 1); // 再帰呼び出し
}
loop(0);
</pre>
<p>一方で、単純な反復ループでは行えないアルゴリズムもあります。例えば、ツリー構造 (例えば <a href="/ja/docs/Web/API/Document_Object_Model">DOM</a>) のすべてのノードを取得する処理は、再帰を使うとより簡単です。</p>
<pre class="brush: js">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">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">入れ子の関数とクロージャ</h3>
<p>関数の中に関数を入れ子に (ネスト) することができます。入れ子になった (内側の) 関数は、それを含んでいる (外側の) 関数の外には非公開となります。</p>
<p>これにより<strong>クロージャ</strong>が作られます。クロージャとは、環境に束縛された (式によって「閉じ込められた」) 変数を自由に持たせることができる式 (通常は一つの関数) のことです。</p>
<p>入れ子になった関数はクロージャなので、これはつまり、入れ子になった関数は内包する関数の引数と変数を「継承」することができるということです。別の言い方をすれば、内側の関数は外側の関数のスコープを持っているということです。</p>
<p>まとめると、次のようになります。</p>
<ul>
<li>内側の関数へは、外側の関数の中にある文からのみアクセスできます。</li>
<li>内側の関数はクロージャを形成します。内側の関数は外側の関数の引数と変数を利用できますが、外側の関数は内側の関数の引数と変数を利用できません。</li>
</ul>
<p>以下の例では入れ子になった関数が示されています。</p>
<pre class="brush: js">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">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">変数の保護</h3>
<p><code>inside</code> が返されるとき、変数 <code>x</code> がどのように保護されるのかに注目してください。クロージャはそれ自身が参照しているすべてのスコープ内の引数と変数を保護することになります。それぞれの呼び出しには異なる引数が渡される可能性があるので、 <code>outside</code> を呼び出すたびに新しいクロージャが作られます。返された <code>inside</code> がもはやアクセスできなくなった時にのみメモリーが解放されます。</p>
<p>これはその他のオブジェクトの内部で参照を保持する場合と違いはないのですが、クロージャの場合は直接参照を設定せず、また情報を取得できないので、明白さは劣ります。</p>
<h3 id="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">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> <em>と</em> <code>A</code> の<em>両方</em>の引数と変数にアクセスできます。言い換えれば、<code>C</code> は <code>B</code>、<code>A</code> の順でスコープがつながっている (<em>chain</em>) のです。</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">名前の衝突</h3>
<p>クロージャ中のスコープに同じ名前の 2 つの引数や変数がある場合、<em>名前の衝突</em>が生じます。より内側のスコープが優先されるので、最も内側にあるスコープが最優先に、最も外側のスコープが最も低い優先度となります。これがスコープチェーンです。チェーンの最初は最も内側のスコープ、そして最後は最も外側のスコープとなります。次の例を見てみましょう。</p>
<pre class="brush: js">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">クロージャ</h2>
<p>クロージャは、 JavaScript でもっとも強力な機能のひとつです。 JavaScript では関数の入れ子が可能であることに加えて、内側の関数が外側の関数内で定義されたすべての変数や関数に対し (外側の関数がアクセスできる、他の変数や関数すべてにも) 自由にアクセスできます。</p>
<p>しかし、外側の関数は内側の関数内で定義された変数や関数にアクセスできません。これは、内側の関数の変数に対する一種のセキュリティ機構を提供します。</p>
<p>また、内側の関数は外側の関数のスコープにアクセスできることから、もし内側の関数が外側の関数よりも長く生存できた場合、外側の関数内で定義された変数や関数は外側の関数よりも長く残る可能性があります。クロージャは、内側の関数が何かしらの形で外側の関数のスコープ外のどこかで使用可能になった場合に作られます。</p>
<pre class="brush: js">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">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">var getCode = (function() {
var apiCode = '0]Eal(eh&2'; // 外側の関数が変更できないようにしたいコード
return function() {
return apiCode;
};
})();
getCode(); // シークレットコードを返す
</pre>
<div class="notecard note">
<p><strong>注:</strong> クロージャを使用する際に注意すべき落とし穴がいくつかあります。</p>
<p>取り囲まれている関数で外部スコープの変数と同じ名前の変数を定義した場合、外部スコープにある変数を再び参照する方法がなくなります。 (プログラムが内部スコープを終了するまで、内部スコープ変数は外部変数を「上書き」します。)</p>
<pre class="example-bad brush: js">var createPet = function(name) { // 外側の関数で "name" という変数を定義します。
return {
setName: function(name) { // 内側の関数も "name" という変数を定義します
name = name; // 外側の関数で定義した "name" へどのようにしてアクセスするのか?
}
}
}
</pre>
</div>
<h2 id="Using_the_arguments_object">arguments オブジェクトの使用</h2>
<p>関数の引数 (argument) は、配列風オブジェクトで管理されます。関数内では、次のようにして渡された引数を指定することができます。</p>
<pre class="brush: js">arguments[i]
</pre>
<p>ここで <code>i</code> は引数の順序を表す数で、 <code>0</code> から始まります。関数に渡された第 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">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">// "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">関数の引数</h2>
<p>ECMAScript 2015 から、新しい形の引数が 2 つあります。それが<em>デフォルト引数</em>と<em>残余引数</em>です。</p>
<h3 id="Default_parameters">デフォルト引数</h3>
<p>JavaScript では、関数の引数は既定で <code>undefined</code> となります。しかし、別の既定値が設定されていれば便利だという状況もあるでしょう。デフォルト引数がここで役に立ちます。</p>
<h4 id="Without_default_parameters_pre-ECMAScript_2015">デフォルト引数がない場合 (ECMAScript 2015 以前)</h4>
<p>以前、既定値を設定する一般的な方法は、関数の本体で引数の値をテストし、<code>undefined</code> だった場合にある値を割り当てる、というものでした。</p>
<p>以下の例では、 <code>b</code> の値が与えられなかった場合、 <code>a*b</code> を評価する際にこの値は <code>undefined</code> となるため、 <code>multiply</code> を呼び出すと <code>NaN</code> が返されます。しかしながら、この例の 2 行目でこの問題を回避しています。</p>
<pre class="brush: js">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">デフォルト引数がある場合 (ECMAScript 2015 以降) </h4>
<p><em>デフォルト引数</em>を使えば、関数本体での引数チェックはもう必要ありません。これからは、関数の最初で単純に <code>b</code> に <code>1</code> を代入することができます。</p>
<pre class="brush: js">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">残余引数</h3>
<p><a href="/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数</a>の構文によって、不特定多数の引数を配列のように表すことができます。</p>
<p>次の例では、2 つ目から最後までの引数をまとめるのに<em>残余引数</em>を使っています。そして最初の引数を使って乗算します。</p>
<pre class="brush: js">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">アロー関数</h2>
<p><a href="/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions">アロー関数式</a> (以前、そして今も誤って<strong>ファットアロー関数</strong>とも呼ばれる) は関数式と比較してより短い構文を持ち、<code><a href="/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code>、<a href="/ja/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>、<a href="/ja/docs/Web/JavaScript/Reference/Operators/super">super</a>、<a href="/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">短縮形の関数</h3>
<p>関数パターンによっては、短縮形の関数がうってつけです。比較してみましょう。</p>
<pre class="brush: js">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">独自の <code>this</code> を持たない</h3>
<p>アロー関数の導入以前は、すべての新しい関数には独自の <a href="/ja/docs/Web/JavaScript/Reference/Operators/this">this</a> 値が定義されていました (コンストラクターの場合は新しいオブジェクトに、 <a href="/ja/docs/Web/JavaScript/Reference/Strict_mode">strict モード</a> の関数呼び出しの場合は undefined に、関数が「オブジェクトのメソッド」として呼び出された場合はその基底オブジェクトに、といったように) 。これはオブジェクト指向プログラミングにとっては厄介です。</p>
<pre class="brush: js">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">function Person() {
var self = this; // `self` の代わりに `that` を選ぶ人もいます。
// どちらか一方を選び、そちらだけを使うようにしましょう。
self.age = 0;
setInterval(function growUp() {
// このコールバックは、その値が期待通りのオブジェクトを指す
// 変数 `self` を参照しています。
self.age++;
}, 1000);
}</pre>
<p>代わりに、<a href="/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">function Person() {
this.age = 0;
setInterval(() => {
this.age++; // `this` は的確に person オブジェクトを参照する
}, 1000);
}
var p = new Person();</pre>
<h2 id="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="/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")}} 関数によって、または同様の方法で作られた URL (Uniform Resource Identifier) をデコードします。</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>
|