吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【JS入門】関数について Vol.2(無名関数、即時関数、アロー関数)

2018年1月15日 / category : javascript

前回の記事では、関数の定義、return文、引数について解説しました。
今回の記事も引き続き関数について解説していきたいと思います。

無名関数

前回の記事で、関数を定義する際、関数名が必要ということで解説しましたが、関数名のない関数を定義することも可能です。関数名がない関数を無名関数と呼びます。次のコードを見てみましょう。

sample.js
var getAge = function(age){
	return age;
}
console.log( getAge(37) );

前回の記事で出てきた関数と似ていますが、上のコードではfunctionの後に関数名がありません。その代わり、getAge変数に関数を代入しています。
getAge変数には無名関数が代入されていますので、実行方法は、変数名+()という形式になります。
次のコードは、無名関数ではありませんが、関数名のある関数を変数に代入することも可能です。

sample.js
var getAge = function getAge2(age){
	return age;
}
console.log( getAge(37) );
console.log( getAge2(37) ); //getAge2 is not defined

関数名付きの関数をgetAge変数に代入し、変数名、関数名で実行した結果です。
変数名では問題なく動作していますが、関数名ではnot defined(定義されていない)という結果になります。
もし関数名で実行したい場合は、次のようになります。

sample.js
function getAge2(age){
	return age;
}
var getAge = getAge2;
console.log( getAge(37) );
console.log( getAge2(37) );

上のコードでは、関数名でも問題なく動作しました。では、先ほどのコードとの違いはなんでしょうか。
これはトップレベルに定義しているかどうかの違いになります。先ほどのコードでは、getAge2関数をgetAge変数に代入する際に定義しているため、トップレベルに定義したことにはならず、上のコードでは、一度トップレベルに定義したgetAge2関数をgetAge変数に代入しています。
トップレベルという言葉が出てきましたので、一度関数の解説から離れ、トップレベルについて解説します。
このトップレベルとは、関数の外という意味になります。
JavaScriptでは、この関数の外(トップレベル)に定義した変数をグローバル変数、関数の中に定義した変数をローカル変数と呼びます。
それではこのグローバル変数とローカル変数の違いについて解説します。

グローバル変数(global変数)とローカル変数(local変数)の違い

JavaScript言語には、変数にアクセスできる範囲にグローバル変数とローカル変数の2種類の範囲があります。
この範囲のことを「スコープ」と呼びます。変数にアクセスできる範囲を具体的に見てみます。

sample.js
var txt = 'お腹減った';
function getMessage(){
	var txt = 'お腹減っていない';
	console.log( txt );
}
console.log( txt ); //お腹減った
getMessage(); //お腹減っていない

上のコードをコンソール画面で確認すると、「お腹減った」「お腹減っていない」の順に表示されていると思います。
これは想像ができたかと思いますが、getMessage関数の外にあるconsole.log( txt )のtxt変数はgetMessage関数の外で定義しているtxt変数を参照し、次にgetMessage関数を実行することで、getMessage関数の関数文の記述にあるconsole.log( txt )は関数内で定義しているtxt変数を参照しています。

関数の外で定義している変数を、グローバル変数と呼びます。
関数の中で定義している変数を、ローカル変数と呼びます。

この2つの変数の違いを確かめます。上のコードを少し変更し、次のようなコードにしました。

sample.js
var txt = 'お腹減った';
function getMessage(){
	console.log( txt );
}
console.log( txt ); //お腹減った
getMessage(); //お腹減った

先ほどのコードからgetMessage関数内で定義していたtxt変数を削除しました。結果は「お腹減った」「お腹減った」とコンソールに表示されました。
getMessage関数にあるtxt変数がグローバルで定義したtxt変数を参照できていることになります。
それでは次のコードを見てみます。

sample.js
function getMessage(){
	var txt = 'お腹減っていない';
}
console.log( txt ); //txt is not defined

上のコードではエラーが起こりました。getMessage関数内で定義したtxt変数(ローカル変数)を参照できないようです。

グローバル変数、ローカル変数の違いは、グローバル変数はプログラムのどこからでも参照ができる。ローカル変数はその関数内のみ参照できる。
ということになります。

変数のスコープについての話が出てきましたので、少し触れておきますが、ES6から変数を宣言する際に使用するlet,constという新しい機能が出来ました。いずれこの記事でも解説しようと思っています。

これで変数のスコープについて、グローバル変数、ローカル変数についてのお話を終わりにし、話を無名関数に戻します。
無名関数は、変数に代入するときによく使用されますが、似たような関数で、即時関数と呼ばれる構文があります。

即時関数

即時関数とは、関数を宣言した直後に実行する関数です。名前付き関数や変数に代入した無名関数などはその関数を再利用できるという特長がありますが、1回だけ実行できれば良い場合は、即時関数を使用します。主に利用されるケースとしてはページの初期化時に実行する場合があげられます。
次のような構文になります。

sample.js
(function(){
	console.log('即時関数です。');
})();

上のコードをコンソール画面で確認すると「即時関数です。」が出ます。これが即時関数の構文です。
function文を()で囲み、続けて実行する際に記述する()を記述します。(function文)+()という形式になります。
もし引数を持たせたい場合は次のようになります。

sample.js
(function(message){
	console.log(message);
})('即時関数です。');

以上が、即時関数の解説です。
関数について、名前付きの関数、無名関数そして即時関数を解説してきましたが、ES6よりもう1つアロー関数という機能が追加されました。
アロー関数は次のようなコードになります。

sample.js
()=>{
	console.log('アロー関数です。');
}

コンソール画面を確認しても何も表示されていません、これはアロー関数を定義しただけの状態です。
引数の持たないアロー関数は次のような構文になります。

()=>{
	関数文
}

アロー関数を実行する場合は、即時関数と同様、(アロー関数)+()という形式になります。

(()=>{
	関数文
})();

上のコードを実行する場合は、次のようになります。

sample.js
(()=>{
	console.log('アロー関数です。');
})();

アロー関数に引数を持たせて実行する場合は、次のような構文になります。

((引数)=>{
	関数文
})(引数の値);

上のコードに引数を設定してみます。

sample.js
((message)=>{
	console.log(message);
})('アロー関数です。');

引数が1つの場合は、()を省略することができます。次のような構文です。

(引数=>{
	関数文
})(引数の値);

上のコードでは、次のようになります。

sample.js
(message=>{
	console.log(message);
})('アロー関数です。');

関数文が1行であれば、関数文を囲っている{}も省略することができます。

sample.js
( message => console.log(message) )('アロー関数です。');

引数が複数の場合は、省略形は使えません。

(引数1,引数2,,,)=>{
	関数文
}

もちろん、ES6で追加された「デフォルト仮引数」「残余仮引数」は使用可能です。
アロー関数は、thisを束縛しないという特長がありますが、これについては別の記事で解説したいと思います。

以上が、アロー関数についてです。
今回の関数については、ここまでとしますが、関数についてもう少し解説したいと思いますので、次回も関数についての記事にします。