マッスル・メモリー

筋肉エンジニアのブログ

【js】 4種類の関数の定義の仕方

Javascriptには関数を定義する方法が4種類あります。

今回はそれらの定義の仕方、特徴についてまとめていきます。

1. function命令で定義する

一番ベーシッックな関数の定義の仕方です。

function getTrainingVolume(weight, rep, set) {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

なお戻り値を返さない関数はreturnを省略できますが、その場合はundefinedを返します。

またこのfunction命令での関数の定義には1つ特徴があります。

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

function getTrainingVolume(weight, rep, set) {
  return weight * rep * set;
};

先ほどのコードと内容は同じですが、宣言する前にgetTrainingVolumeを実行しています。

これはまだ関数が定義されていない状態ですので、エラーになるはずです。

しかし、結果は問題なく実行されます。

実はfunction命令は静的な構造を宣言するためのキーワードであるからなのです。

静的な構造という言葉が難しいですが、要は、

function命令はコードを解析/コンパイルするタイミングで関数を登録している。

のです。

なので、実行時にすでにgetTrainingVolume関数がどこからでも呼び出せる状態なのです。

2. Functionコンストラクター経由で定義する

let getTrainingVolume = new Function('weight', 'rep', 'set', 'return weight * rep * set;');

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

2は引数や関数本体を文字列として定義できるという特徴があるだけで基本使われません。

1. function命令で定義する

3. 関数リテラル表現で定義する

4. アロー関数で定義する(ES6)

で関数は基本的に定義すると覚えましょう。

3. 関数リテラル表現で定義する

リテラルとは、データ型に格納できる値そのものです。

例えば、

- 文字リテラル 'hello, world'

- 数値リテラル(10進数リテラル) 100

などです。

つまり、関数リテラルとは

文字列や数値と同ように変数に代入したり、ある関数の引数に渡したり、戻り値として関数を返すことが可能ということです。

let getTrainingVolume = function(weight, rep, set) {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

このように宣言します。

また、1と同じように関数が宣言される前に実行させるとどうなるでしょうか?

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// Cannot access 'getTrainingVolume' before initialization

let getTrainingVolume = function(weight, rep, set) {
  return weight * rep * set;
};

すると、エラーが吐かれます。

1と3の違いをまとめるとこうです。

1. function命令での定義

→関数getTrainingVolumeを直接定義している

→コードを解析/コンパイルするタイミングで関数を登録しているのでコードのどこからでも呼び出せる。

3. 関数リテラル表現での定義

→名前のない関数を定義した上で変数getTrainingVolumeに格納している

→実行時に評価されるので、呼び出し元のコードより前で関数を定義しなくてはいけない。(2のFunctionコンストラクターも同じ)

関数リテラルは宣言した時点では、名前を持たないことから匿名関数、または無名関数と呼ばれることがあります。

4. アロー関数で定義する(ES6)

アロー関数を利用することで関数リテラルをよりシンプルに記述できます。

let getTrainingVolume = (weight, rep, set) => {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

アロー関数ではfunctionキーワードは書きません。

その代わりに=>アローで引数と関数をつなげます。

アロー関数ではさらにシンプルに書ける場合があります。

処理が1行の場合は

let getTrainingVolume = (weight, rep, set) => weight * rep * set;

さらに、引数が1つの場合は、

let getSquare = sideLength => sideLength ** 2 ;

ただし、引数がない場合は()を省略できません。

let sayHello = () => console.log('hello, world') ;

まとめ

1. function命令で定義する

function getTrainingVolume(weight, rep, set) {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです
  • 関数getTrainingVolumeを直接定義している
  • 実行時にすでにgetTrainingVolume関数がどこからでも呼び出せる状態

2. Functionコンストラクター経由で定義する

let getTrainingVolume = new Function('weight', 'rep', 'set', 'return weight * rep * set;');

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです
  • 引数や関数本体を文字列として定義できる
  • 実行時に評価されるので、呼び出し元のコードより前で関数を定義しなくてはいけない
  • 基本使わない

3. 関数リテラル表現で定義する

let getTrainingVolume = function(weight, rep, set) {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです
  • 匿名関数、または無名関数を定義した上で変数getTrainingVolumeに格納している
  • 実行時に評価されるので、呼び出し元のコードより前で関数を定義しなくてはいけない

4. アロー関数で定義する(ES6)

let getTrainingVolume = (weight, rep, set) => {
  return weight * rep * set;
};

console.log(`ベンチプレスのトレーニングボリュームは${getTrainingVolume(100, 8, 5)}kgです`);
// ベンチプレスのトレーニングボリュームは4000kgです

処理が1行の場合

let getTrainingVolume = (weight, rep, set) => weight * rep * set;

処理が1行、引数が1つの場合

let getSquare = sideLength => sideLength ** 2 ;

処理が1行、引数がない場合

let sayHello = () => console.log('hello, world') ;