関数を使ってみよう

目次

関数とは

関数とは、呼び出すとさまざまな処理を行ってくれるものです。
自分で関数を作ることもでき、よく使う処理や複数の処理をまとめることができます。
関数がオブジェクトの中に入っている場合は、メソッドと呼ばれます。

ウィンドウにアラートを表示できる window.alert() は、window オブジェクトの中にある alert() メソッドを呼び出しているということになります。

1
window.alert('Hello, kintone');

関数宣言

関数の基本の形は、次のとおりです。

1
2
3
function 関数名(パラメーター) {
  処理
}

まずは、window.alert() を実行する関数を作ってみましょう。
関数名には処理を理解しやすい名前をつけるようにします。
今回はアラートを表示する関数ですから、showAlert という名前をつけます。
なお、パラメーターはこの後説明しますので空欄にしておきます。

1
2
3
function showAlert() {
  window.alert('初めての関数');
}

呼び出し

作成した関数の呼び出し方は次のとおりです。

1
関数名();

今回の関数名は showAlert ですので、次のように呼び出します。

1
showAlert();

パラメーター(引数)

パラメーターは、関数に渡す値です。引数(ひきすう)とも呼ばれます。
今回のように特定の処理を行う場合にはパラメーターは不要ですが、実行するごとにアラートへ表示する値を変えたいときは、パラメーターを利用します。
次のようにコードを書き換えてみましょう。

1
2
3
function showAlert(message) {
  window.alert(message);
}

指定したパラメーター(message)は、処理内で利用できます。 実行時に値を渡すことで、都度表示する値を変えることができます。

1
2
showAlert('初めての関数');
showAlert('2回目の関数');

return

関数の処理部で return を用いることで、値が返されます。この値を 戻り値 と呼びます。
今回は商品価格を渡すと、割り引き後の価格が返ってくるコードを書いてみましょう。

1
2
3
function calcDiscountedPrice(price) {
  return price * 0.8; // 2割引した価格を返す
}

パラメーターprice に 0.8 を乗算した値を return します。
後は実行時に商品価格を渡してあげるだけです。

1
calcDiscountedPrice(5000); // 実行結果 4000

関数式

関数は、関数式を用いた定義もできます。
基本の形は次のとおりです。

1
2
3
const 変数名 = function 関数名 (パラメーター) {
  処理
};

関数名を省略して書くことが多いです。これを無名関数と言います。

1
2
3
const 変数名 = function (パラメーター) {
  処理
};

実行時には、変数名で呼び出します。

1
変数名();

関数宣言と関数式には、見た目以外にも違いがあります。
ここで理解しておくべきなのは、関数の巻き上げです。
JavaScript では基本的にコードが書かれた順に実行されるため、定義→実行の順でコードを書きます。
しかし、関数宣言の場合、定義より前に実行しても、関数が前に定義されたと判断されて正常に実行されます。
これが関数の巻き上げです。

1
2
3
4
5
calcDiscountedPrice(5000); // 巻き上げられてエラーにならない

function calcDiscountedPrice(price) {
  return price * 0.8;
}

一方、関数式の場合は、巻き上げが起こらずエラーになります。

1
2
3
4
5
calcDiscountedPrice(5000); // 巻き上げられずエラーになる

const calcDiscountedPrice = function(price) {
  return price * 0.8;
};

不要なエラーを防ぐためにも、定義→実行の順にコードを書いていくようにしましょう。

アロー関数

ES2015 からはアロー関数が使えるようになりました。
アロー関数を使うと従来の書き方よりもシンプルに書くことができますが、一部制限があります。
詳しくは、 MDN Web Docs (External link) を参照してください。

従来の関数式
1
2
3
const 変数名 = function (パラメーター) {
  処理
};
アロー関数の関数式
1
2
3
const 変数名 = (パラメーター) => {
  処理;
};

スコープ

スコープとは

JavaScript では、値や式を参照できる範囲が決まっています。
これをスコープと言います。 次の例にある変数 subjects は、関数内で定義されているため、関数外からはアクセスできません。
関数を使ったスコープのことを、関数スコープと呼びます。

1
2
3
4
5
6
7
8
function calcAve(score) {
  const subjects = 5;
  console.log(subjects); // 実行結果 5
  return score / subjects;
}

calcAve(455);
console.log(subjects); // エラー

次の場合は、関数外で変数 subjects を定義しているため、subjects にはアクセスできます。

1
2
3
4
5
6
7
8
9
const subjects = 5;

function calcAve(score) {
  console.log(subjects); // 実行結果 5
  return score / subjects;
}

calcAve(455);
console.log(subjects); // 実行結果 5

グローバルスコープ

コード内のどこからでも変数を参照できるスコープのことを、グローバルスコープと呼びます。
たとえば、console.log() は、どこで実行しても () 内に指定したテキストや変数をコンソールにアウトプットできました。
console は、グローバルスコープ内にある、ブラウザーが標準で用意している変数だからです。

即時関数によるスコープ

関数は、関数宣言した後に呼び出しすることでその関数内の処理を実行できました。

1
2
3
4
5
6
7
8
function sayHello(name) {
  const message = `Hello ${name}!`;
  console.log(message);
}
// 関数内の処理は実行されない

sayHello('kintone');
// 関数内の処理が実行され、「Hello kintone!」が出力される

即時関数(即時実行関数)とは、関数宣言されるとすぐに実行される関数のことです。
即時関数で宣言する関数には名前をつけないため、自己実行無名関数とも呼ばれます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(() => {
  console.log('Hello World!');
})();
// 宣言と同時に実行され、「Hello World!」が出力される

// 引数を渡すこともできる
((name) => {
  const message = `Hello ${name}!`;
  console.log(message);
})('kintone');
// 「Hello kintone!」と出力される

先ほど説明したとおり、関数内で定義した変数は関数外からアクセスできません。関数内と関数外のスコープが異なるからです。

即時関数も同様で、即時関数内で関数スコープが作られるため、即時関数内で定義した変数には、関数外からアクセスできません。
裏を返すと、即時関数外で定義した変数には影響を与えません。そのためグローバルスコープ内の変数を上書きしてしまうことを防げます。
kintone のカスタマイズでも、kintone が標準で用意している変数の上書きを防ぐために、即時関数やこのあと紹介するブロックスコープの形式を利用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
((name) => {
  const message = `Hello ${name}!`;
  console.log(message);
})('kintone');

console.log(message);

// 即時関数内で宣言した message は、即時関数外からアクセスできない
// VM126:7 Uncaught ReferenceError: message is not defined
// at <anonymous>:7:13

ブロックによるスコープ

{} とで区切られた範囲をブロックと呼びます。
ブロック内では新しくスコープが作られるため、ブロック内で定義した変数はブロック外からアクセスできません。
ブロックを使ったスコープのことを、ブロックスコープと呼びます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  const product = 'kintone';
  console.log(product);
  // 「kintone」と出力される
}
console.log(product);

// product はブロック内で宣言されているため、ブロック外からはアクセスできない
// VM275:6 Uncaught ReferenceError: product is not defined
//    at <anonymous>:6:13

ただし、ブロックスコープが有効になるのは constlet で定義した変数だけです。
変数宣言 の補足で紹介した var を使って定義した変数は、ブロック外からもアクセスできてしまいます。
つまり、ブロックを使ってスコープで作ったとしても、var で定義してしまうと、他の変数を上書きしてしまう可能性があります。

1
2
3
4
5
6
7
{
  var unBlockedVar = 'varで定義した変数です';
}
console.log(unBlockedVar);

// ブロック内で var で定義した変数は、ブロック外からもアクセスできてしまう
// 「varで定義した変数です」と出力される

意図どおりにスコープを扱うためにも var は使わず、const または let を使って変数を定義しましょう。

まとめ

関数を使うことで、多くのメリットがあります。
同じような処理をまとめることでコードの可読性が向上し、メンテナンスもしやすくなります。
また、どこからでも呼び出せるようになるので、再利用がしやすくなります。
次回は イベント について学習しましょう。