JavaScript

JavaScriptの関数・スコープ・モジュール:処理を再利用する方法

この記事でわかること

JavaScriptの関数、引数と戻り値、アロー関数、クロージャー、exportとimportを実例で解説。平均値の計算と独立したカウンターを作ります。

第2回では、引数から結果を返す関数、変数が使える範囲であるスコープ、関数が外側の値を保持するクロージャーを学びます。最後にファイルを分割し、exportimportで処理を再利用します。前提は基本構文の記事です。

関数の入力と出力を決める

returnで計算結果を返す

関数は引数を受け取り、returnで呼び出し元へ値を返します。console.logは表示する処理であり、戻り値を返す処理とは別です。入力の検証、計算、表示を分けると、同じ計算を別の画面からも使いやすくなります。

stats.mjsを作成する

作業用フォルダーにstats.mjsを作成します。配列が空の場合や、有限な数値以外が入っている場合を拒否し、平均値を計算します。

export function average(values) {
  if (!Array.isArray(values) || values.length === 0) {
    throw new TypeError('空でない配列を渡してください。');
  }
  let total = 0;
  for (const value of values) {
    if (!Number.isFinite(value)) {
      throw new TypeError('すべての要素を有限な数値にしてください。');
    }
    total += value;
  }
  return total / values.length;
}

export const formatAverage = (value) => `平均:${value.toFixed(1)}`;

export function createCounter(initialValue = 0) {
  let count = initialValue;
  return () => {
    count += 1;
    return count;
  };
}

スコープとクロージャーを理解する

関数の中の変数を外から直接使わない

totalaverageの中で宣言され、その関数内の計算に使います。処理の途中の値をグローバル変数へ置かず、必要な結果を戻り値として公開します。

letconstにはブロックスコープがあります。条件分岐やループのブロック内で宣言した変数は、通常その外から参照できません。

クロージャーで別々の状態を保持する

createCounterが返す関数は、外側のcountを参照し続けます。これがクロージャーの例です。呼び出すたびに別のcountが作られるため、2つのカウンターを独立させられます。

この例では初期値に数値を渡す前提です。外部入力を受け付ける部品にするなら、Number.isSafeIntegerなどによる範囲と型の検証も追加してください。

importして利用する

main.mjsを作成する

stats.mjsと同じフォルダーにmain.mjsを作成します。相対パスには拡張子を含めます。

import { average, formatAverage, createCounter } from './stats.mjs';

console.log(formatAverage(average([80, 65, 92]))); // 平均:79.0
console.log(formatAverage(average([100, 80]))); // 平均:90.0

const first = createCounter();
const second = createCounter(10);
console.log(first()); // 1
console.log(first()); // 2
console.log(second()); // 11

try {
  average([]);
} catch (error) {
  console.log(error.message);
}

モジュールを実行する

Node.jsで次のコマンドを実行します。stats.mjsには表示処理を置いていないので、importしただけで勝手に例が動くことはありません。

node main.mjs

アロー関数と通常の関数

短い変換にアロー関数を使う

formatAverageのような短い式はアロー関数で書けます。波括弧を使う関数本体では、結果を返すために明示的なreturnが必要です。省略できるのは式をそのまま本体にした場合です。

thisの扱いは同じではない

アロー関数には独自のthisがなく、外側のthisを使います。通常の関数のthisは呼び出し方によって変わります。メソッドとコールバックの違いは、後のクラス入門で扱います。

練習と関連資料

入力の境界を試す

  • average([0])の結果を確認します。
  • average([80, '90'])が文字列を拒否することを確認します。
  • createCounter()を3つ作り、互いの値が混ざらないことを確認します。

次に配列とオブジェクトを学ぶ

次は配列とオブジェクトの実践で、商品の絞り込み・変換・集計を実装します。

参考資料

y.
WRITTEN BY

y_ymo10

SEの部屋で、JavaScript・TypeScript・React.js・Next.jsの開発ノートを公開しています。

ほかの開発ノートを読む →