LoginSignup
7
3

More than 3 years have passed since last update.

JavaScript の関数宣言、関数式、アロー関数式、Function コンストラクタの違い

Last updated at Posted at 2019-08-24

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
})();

関数を動的に生成できるという利点はあるが、パフォーマンスは関数宣言や関数式に比べて劣る。

7
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3