JavaScript関数はファーストクラスオブジェクトです

概要: このチュートリアルでは、JavaScript関数がファーストクラスオブジェクトであることを学習します。これは、関数を変数に格納し、他の関数に引数として渡し、他の関数から値として返すことができることを意味します。

変数への関数の格納

関数はJavaScriptでファーストクラスオブジェクトです。つまり、関数を他の型の値のように扱うことができます。

以下は、add()関数を定義し、関数名をsum変数に代入する例です。

function add(a, b) {
    return a + b;
}

let sum = add;Code language: JavaScript (javascript)

代入文では、add識別子の後ろに開き括弧と閉じ括弧を付けません。関数を実行するのではなく、関数を参照します。

これにより、同じ関数を2つの方法で実行できます。例えば、通常どおり次のように呼び出すことができます。

let result = add(10, 20);Code language: JavaScript (javascript)

あるいは、次のようにsum変数を通してadd()関数を呼び出すこともできます。

let result = sum(10,20);Code language: JavaScript (javascript)

関数を別の関数に渡す

関数は値であるため、関数を引数として別の関数に渡すことができます。

以下は、3つの引数をとるaverage()関数を宣言した例です。3番目の引数は関数です。

function average(a, b, fn) {
    return fn(a, b) / 2;
}Code language: JavaScript (javascript)

これで、次のようにsum関数をaverage()関数に渡すことができます。

let result = average(10, 20, sum);Code language: JavaScript (javascript)

全てをまとめて

function add(a, b) {
    return a + b;
}

let sum = add;

function average(a, b, fn) {
    return fn(a, b) / 2;
}

let result = average(10, 20, sum);

console.log(result);Code language: JavaScript (javascript)

出力

15

関数から関数を返す

関数は値であるため、関数から別の関数を返すことができます。

次のcompareBy()関数は、プロパティで2つのオブジェクトを比較する関数を返します。

function compareBy(propertyName) {
  return function (a, b) {
    let x = a[propertyName],
      y = b[propertyName];

    if (x > y) {
      return 1;
    } else if (x < y) {
      return -1;
    } else {
      return 0;
    }
  };
}Code language: JavaScript (javascript)

a[propertyName]は、aオブジェクトのpropertyNameの値を返します。これはa.propertyNameと同等です。ただし、propertyNameに「Discount Price」のようなスペースが含まれる場合は、角括弧表記を使用してアクセスする必要があります。

各製品オブジェクトにnamepriceの2つのプロパティを持つ製品オブジェクトの配列があるとします。

let products = [
    {name: 'iPhone', price: 900},
    {name: 'Samsung Galaxy', price: 850},
    {name: 'Sony Xperia', price: 700}
];Code language: JavaScript (javascript)

配列をソートするには、sort()メソッドを呼び出します。sort()メソッドは、配列の2つの要素を比較する関数を引数として受け取ります。

例えば、compareBy()関数から返された関数を渡すことで、名前に基づいて製品オブジェクトをソートできます。

console.log('Products sorted by name:');
products.sort(compareBy('name'));

console.table(products);Code language: JavaScript (javascript)

出力

Products sorted by name:
┌─────────┬──────────────────┬───────┐
│ (index) │       name       │ price │
├─────────┼──────────────────┼───────┤
│    0    │ 'Samsung Galaxy' │  850  │
│    1    │  'Sony Xperia'   │  700  │
│    2    │     'iPhone'     │  900  │
└─────────┴──────────────────┴───────┘Code language: plaintext (plaintext)

同様に、価格で製品オブジェクトをソートすることもできます。

// sort products by prices

console.log('Products sorted by price:');
products.sort(compareBy('price'));
console.table(products);Code language: JavaScript (javascript)

出力

Products sorted by price:
┌─────────┬──────────────────┬───────┐
│ (index) │       name       │ price │
├─────────┼──────────────────┼───────┤
│    0'Sony Xperia'700  │
│    1'Samsung Galaxy'850  │
│    2'iPhone'900  │
└─────────┴──────────────────┴───────┘Code language: JavaScript (javascript)

全てをまとめて。

function compareBy(propertyName) {
  return function (a, b) {
    let x = a[propertyName],
      y = b[propertyName];

    if (x > y) {
      return 1;
    } else if (x < y) {
      return -1;
    } else {
      return 0;
    }
  };
}
let products = [
  { name: 'iPhone', price: 900 },
  { name: 'Samsung Galaxy', price: 850 },
  { name: 'Sony Xperia', price: 700 },
];

// sort products by name
console.log('Products sorted by name:');
products.sort(compareBy('name'));

console.table(products);

// sort products by price
console.log('Products sorted by price:');
products.sort(compareBy('price'));
console.table(products);
Code language: JavaScript (javascript)

JavaScript関数はファーストクラスオブジェクトのさらなる例

次の例では、センチメートル単位の長さをインチ単位に変換し、その逆を行う2つの関数を定義します。

function cmToIn(length) {
    return length / 2.54;
}

function inToCm(length) {
    return length * 2.54;
}Code language: JavaScript (javascript)

次のconvert()関数は2つのパラメータを持ちます。最初の引数は関数で、2番目の引数は最初の引数に基づいて変換される長さです。

function convert(fn, length) {
    return fn(length);
}Code language: JavaScript (javascript)

cminに変換するには、convert()関数を呼び出し、cmToIn関数をconvert()関数の最初の引数として渡します。

let inches = convert(cmToIn, 10);
console.log(inches);Code language: JavaScript (javascript)

出力

3.937007874015748Code language: CSS (css)

同様に、インチからセンチメートルへの長さを変換するには、次のようにinToCm関数をconvert()関数に渡します。

let cm = convert(inToCm, 10);
console.log(cm);Code language: JavaScript (javascript)

出力

25.4Code language: CSS (css)

全てをまとめて。

function cmToIn(length) {
  return length / 2.54;
}

function inToCm(length) {
  return length * 2.54;
}

function convert(fn, length) {
  return fn(length);
}

let inches = convert(cmToIn, 10);
console.log(inches);

let cm = convert(inToCm, 10);
console.log(cm);Code language: JavaScript (javascript)

出力

3.937007874015748
25.4Code language: CSS (css)

まとめ

  • 関数はJavaScriptでファーストクラスオブジェクトです。
  • 関数を引数として他の関数に渡したり、値として他の関数から返したり、変数に格納したりできます。
このチュートリアルは役に立ちましたか?