関数・導入

関数・導入

関数とは

関数とはまとまった処理を実行できるサブプログラムのようなものです。
サブプログラムとはメインプログラムから呼び出される、一連の処理群のことです。
分岐処理の章で説明したように、ソースコードを上から順に実行していきます。

<!DOCTYPE html>
<html lang="ja" dir="ltr">
	<head>
		<meta charset="utf-8">
		<title>開発環境</title>
	</head>
	<body>
		<script src="JavaScript/function1.js" charset="utf-8"></script>
		<script src="JavaScript/function2.js" charset="utf-8"></script>
	</body>
</html>
let str = 'function1';
alert(str);
// let str = 'function2';
alert('function2');

上記のHTMLとJS(JavaScript)ファイルを用意し、実行してみてください。
1回目のダイアログには'function1'という文字列が、
2回目のダイアログには'function2'という文字列が表示されます。
二つのファイルを上から順に読み込み・実行しているため、このような結果となります。
関数とはこの二つに分けたソースファイルのようなものです。
ちなみに function2.js のコメントアウトを外すと、エラーになります。
ソースファイルを分けていても、同じ変数名を宣言できません。
大切なことです。

関数の定義方法

さて、早速定義してみましょう。

/**
* function 関数名(引数リスト) {
*   処理
*   return 結果
* }
* return 結果 とすることで、呼び出し元に値を返すことができます。
* return文がない場合は、暗黙的に undefined を返します。
*/
function calcTax(price) {
	const tax = 1.1;	// 10%
	const priceIncludingTax = Math.floor(price * tax);
	return priceIncludingTax;
}

税抜き金額を税込み金額にして返却する関数を定義してみました。
定義方法は、コメントにある通りです。
関数には変数名と同じように好きな名前を付けることができますが、わかりやすい名前にした方がみんな幸せになれます。
また、上記の記述だけでは、何も起こらないことがわかるかと思います。
単なる関数は実行されるまで何も行いません。
定義(宣言)しただけ、ということですね。
と言うことで、実行してみましょう。

実行・使い方

// 実行してみる
const price = 90000;
// 関数名(引数)
const priceIncludingTax = calcTax(price);
console.log(priceIncludingTax); // 99000

ハイライトした行で関数を実行しています。
今回は return文 を書いたので、関数の戻り値として税込み金額が priceIncludingTax に格納(代入)されます。
そしてもう一つ、calcTax 関数の中で priceIncludingTax を宣言し、実行の際にも同じ変数名 priceIncludingTax を宣言しています。
ですがエラーになりません。
下記を試してみてください

// グローバルスコープ
let i = 'グローバルスコープのi';
for(let i = 0; i < 5; i ++) {
  // for文のスコープ
  console.log(i);
  if(i === 4) {
    // if文のスコープ
    let i = 'if文の中のi';
    console.log(i);
    i = 4; // for文のスコープ内の i に代入する
    // if文のスコープここまで
  }
  // for文のスコープここまで
}
console.log('for文終了後');
console.log(i);

特徴

実行してみるとソースコード内で何度も同じ変数を宣言していますがエラーにならないことがわかります。
また、コンソールに出力される値もまるで違います。
これを変数のスコープといい、関数の中で宣言した変数は関数の中からしか参照できなくなります
他にも繰り返し文(for)や条件分岐文(if)の中で宣言した変数も、そのブロック内でしか参照できません。
ですので、

// グローバルスコープ
// let i = 'グローバルスコープのi';
for(let i = 0; i < 5; i ++) {
  // for文のスコープ
  console.log(i);
  if(i === 4) {
    // if文のスコープ
    i = 'if文の中のi';
    console.log(i);
    i = 4; // for文のスコープ内の i に代入する
    // if文のスコープここまで
  }
  // for文のスコープここまで
}
console.log('for文終了後');
console.log(i);  // エラー Uncaught ReferenceError: i is not defined

2行目をコメントアウトすると i という変数が見つからないよ!というエラーになります。
関数一つに一つの機能を持たせてあげると、グローバルスコープが汚れず、変数名などの心配事が減るというわけです。

まとめ

関数にはスコープというものがある。
スコープ内の変数にはスコープ外からアクセスできない。
関数一つに一つの機能を持たせると便利。
最初はこれだけで十分だと思います。
もっと詳しい(わかりにくい)記事はこちら