JavaScript では関数もオブジェクト。関数オブジェクトの作成方法には、Function コンストラクタ、関数宣言(function declaration)、関数式(function expression)があり、関数式には従来の関数式とアロー関数式(arrow function expression)がある。
関数宣言は、昔はよく使われたけれど、今では使わないほうがいいと思う。アロー関数式は関数式の糖衣構文ではないので注意。Function コンストラクタの使用は推奨されない。
関数宣言
文(statement)が function
で始まると関数宣言となる。関数宣言は }
で終わる文なので、末尾にセミコロンをつけない。
関数宣言は、var
と同様に巻き上げ(hoist)られるので、宣言の前に使うことができる。
sum = plus(3, 2);
console.log(sum); // 5
var sum;
function plus(x, y) {
return x + y;
}
関数式
関数式は関数オブジェクトを返す式。これも }
で終わるけれど、これ自体は式なので、文の末尾にセミコロンをつける。
普通は無名の関数オブジェクトを作成する。変数に格納すると、変数名を使って関数を呼び出せる。
let sum;
const plus = function(x, y) {
return x + y;
};
sum = plus(3, 2);
console.log(sum); // 5
ほかの関数に引数として渡すこともよくある。
let sum;
sum = [3, 2].reduce(function(x, y) {
return x + y;
});
console.log(sum); // 5
即時実行関数式(Immediately Invoked Function Expression: IIFE)も作れる。関数宣言にならないように、function
の前に何かつける
(function(x, y) {
console.log(x + y);
})(3, 2); // 5
!function(x, y) {
console.log(x + y);
}(3, 2); // 5
関数式でも関数に名前をつけることができる。自分自身を再帰的に呼び出す場合などに使う。関数名のスコープは関数自体であることに注意。
const f = function(n) {
return 0;
};
const factorial = function f(n) {
return n > 1 ? n * f(n - 1) : 1;
};
console.log(f(5)); // 0
console.log(factorial(5)); // 120
アロー関数式
アロー関数式を使うと、関数式を短く書ける。
let sum;
const plus = (x, y) => {
return x + y;
};
sum = plus(3, 2);
console.log(sum); // 5
この例のように関数の本体が 1 つの return
文だけなら、さらに短く書ける。
let sum;
const plus = (x, y) => x + y;
sum = plus(3, 2);
console.log(sum); // 5
引数が 1 つの場合、引数を囲む括弧を省略できる。
const isEven = x => x % 2 === 0;
console.log(isEven(2)); // true
アロー関数式は関数式の短縮形ではない。もっとも重要な違いは this
が束縛(bind)されないこと。
this.x = 0; // this はグローバルオブジェクト
const object1 = {
x: 1,
log: function() {console.log(this.x);}
};
const object2 = {
x: 2,
log: () => {console.log(this.x);}
};
object1.log(); // 1(this は object1)
object2.log(); // 0(this はグローバルオブジェクト)
jQuery でアロー関数式を使うときは注意。
$('input').on('click', function() {
const width = $(this).width(); // this は input 要素
console.log(width); // クリックされた要素の幅
});
$('button').on('click', () => {
const width = $(this).width(); // this はグローバルオブジェクト
console.log(width); // ブラウザウィンドウの幅
});
Function コンストラクタ
Function
コンストラクタで関数オブジェクトを作成するには、引数の名前と関数の本体を文字列として渡す。
let sum;
const plus = new Function('x', 'y', 'return x + y;');
sum = plus(3, 2);
console.log(sum); // 5
なお、new
は省略できる。作成される関数オブジェクトのスコープは常にグローバル。
const x = 0;
(() => {
const x = 1;
const logger1 = function() {console.log(x);};
const logger2 = Function('console.log(x);');
logger1(); // 1
logger2(); // 0
})();
関数を動的に生成できるという利点はあるが、パフォーマンスは関数宣言や関数式に比べて劣る。