この本には、JavaScriptの基礎的な文法や構文だけでなく、実際のアプリケーションやWebページを作る上で必要な機能やライブラリについても詳しく解説しています。しかし、本書で扱った内容だけでアプリケーションを作ることはできず、実際の開発現場ではより高度な機能が必要になることがあります。

そこで、本書で学んだ基礎的な知識を元に、実際に使える応用例を紹介する「コードギャラリー」を用意しました。このコードギャラリーでは、実際のアプリケーションやWebページで使用されるような機能を実現するためのコードを多数掲載しています。

このコードギャラリーを通じて、JavaScriptの応用的な知識や開発技術を身につけ、より実践的な開発に挑戦していただければ幸いです。

エラトステネスの篩

編集
/**
 * エラトステネスの篩を用いて、n以下の素数を全て出力する関数
 * @param {number} n 素数を探す範囲の上限値
 * @returns {void}
 */
function eratosthenes(n) {
  const sieve = new Array(n + 1).fill(true);
  sieve[0] = false;
  sieve[1] = false;

  for (let i = 2; i < sieve.length; i++) {
    if (!sieve[i]) {
      continue;
    }
    console.log(i);

    for (let j = i * 2; j < sieve.length; j += i) {
      sieve[j] = false;
    }
  }
}

// Example usage
eratosthenes(100);

このコードは、エラトステネスの篩を用いて、指定された範囲内の素数を全て出力するJavaScriptの関数です。

関数本体では、まず指定された上限値+1の長さを持つBoolean型の配列sieveを作成し、全ての要素をtrueに初期化しています。その後、最初の2つの要素01は素数ではないため、falseに設定しています。

sieve配列の要素を順番に調べていくforループの中では、もしsieve[i]falseであれば、その数はすでに素数ではないため、次のループに移ります。そうでなければ、素数であることが確定されるため、その数を出力しています。そして、その素数の倍数であるsieve[j]の要素をfalseに設定していくことで、篩にかけた結果、素数ではない数を除外していきます。

最後に、この関数を実行するためのサンプルとして、eratosthenes(100)を呼び出しています。これにより、1から100までの素数が全て出力されます。

別解

編集

エラトステネスの篩ではありませんが、素朴に素数を求めるアルゴリズムです。

const primes = [];

for (let i = 2; i < 1000; i++) {
    if (primes.every(prime => i % prime !== 0)) {
        primes.push(i);
    }
}

console.log(primes)

このJavaScriptコードは、2から999までの範囲で素数を見つけ、その結果をprimesという配列に格納し、最終的にコンソールに表示しています。以下にコードの各部分の説明を記載します。

  1. const primes = [];: 空の配列primesを宣言しています。この配列に素数が保存されます。
  2. for (let i = 2; i < 1000; i++) {: iを2から始め、999まで1ずつ増加させるループを設定しています。これにより、2から999までの数字を順番に取得します。
  3. if (primes.every(prime => i % prime !== 0)) {: everyメソッドを使用して、primes配列内の要素を順に対して条件を確認しています。条件は、iが配列内の任意の素数で割り切れないことです。すなわち、iが素数であるかどうかを確認しています。割り切れたらeveryメソッドは即時にfalseを返します。primesは小さい素数から順に並んでいるので素早く因数を発見できます。
  4. 条件が真であれば、primes.push(i);が実行されます。これにより、primes配列にiが追加されます。なぜなら、iが素数であると確認できたからです。
  5. console.log(primes);: 最終的に、すべてのループが終了した後に、primes配列をコンソールに表示します。これにより、2から999までの範囲で見つかった素数が表示されます。

このコードは、エラトステネスの篩などのアルゴリズムを使用せずに、単純に素数を見つける方法の一例です。

最大公約数と最小公倍数

編集
/**
 * 2つの整数の最大公約数を再帰的に求める関数
 * @param {number} m - 整数1
 * @param {number} n - 整数2
 * @returns {number} - 整数1と整数2の最大公約数
 */
function gcd2(m, n) {
  if (n === 0) {
    return m;
  } else {
    return gcd2(n, m % n);
  }
}

/**
 * 複数の整数の最大公約数を求める関数
 * @param {...number} ints - 最大公約数を求める整数配列
 * @returns {number} - 与えられた整数配列の最大公約数
 */
function gcd(...ints) {
  return ints.reduce((x, y) => gcd2(x, y));
}

/**
 * 2つの整数の最小公倍数を求める関数
 * @param {number} m - 整数1
 * @param {number} n - 整数2
 * @returns {number} - 整数1と整数2の最小公倍数
 */
function lcm2(m, n) {
  return m * n / gcd2(m, n);
}

/**
 * 複数の整数の最小公倍数を求める関数
 * @param {...number} ints - 最小公倍数を求める整数配列
 * @returns {number} - 与えられた整数配列の最小公倍数
 */
function lcm(...ints) {
  return ints.reduce((x, y) => lcm2(x, y));
}

/**
 * テストコード
 */
function main() {
  console.log(`gcd2(30, 45) => ${gcd2(30, 45)}`);
  console.log(`gcd(30, 72, 12) => ${gcd(30, 72, 12)}`);
  console.log(`lcm2(30, 72) => ${lcm2(30, 72)}`);
  console.log(`lcm(30,42,72) => ${lcm(30,42,72)}`);
}

main();

このJavaScriptコードは、与えられた整数の最大公約数と最小公倍数を求めるための関数を定義しています。また、それらの関数をテストするためのmain()関数も定義しています。

まず、gcd2()関数は、2つの整数を引数に取り、再帰的に最大公約数を求める関数です。JSDocコメントで、引数mとnが整数であることを指定し、戻り値として整数1と整数2の最大公約数を返すことを明記しています。

次に、gcd()関数は、可変長引数を受け取り、reduce()メソッドを使って複数の整数の最大公約数を求める関数です。JSDocコメントで、可変長引数...intsが最大公約数を求める整数配列であることを指定し、戻り値として与えられた整数配列の最大公約数を返すことを明記しています。

次に、lcm2()関数は、2つの整数を引数に取り、最小公倍数を求める関数です。JSDocコメントで、引数mとnが整数であることを指定し、戻り値として整数1と整数2の最小公倍数を返すことを明記しています。

最後に、lcm()関数は、可変長引数を受け取り、reduce()メソッドを使って複数の整数の最小公倍数を求める関数です。JSDocコメントで、可変長引数...intsが最小公倍数を求める整数配列であることを指定し、戻り値として与えられた整数配列の最小公倍数を返すことを明記しています。

最後に、main()関数は、それぞれの関数を呼び出してテストするためのものです。

二分法

編集

二分法

/**
 * 2分法による方程式の数値解を求める関数
 * @param {number} low_ - 下限値
 * @param {number} high_ - 上限値
 * @param {(x: number) => number} f - 数値解を求める対象となる関数
 * @returns {number} 方程式の数値解
 */
function bisection(low_, high_, f) {
    let low = low_;
    let high = high_;
    let x = (low + high) / 2;
    let fx = f(x);
    if (Math.abs(fx) < +1.0e-10) {
        return x;
    }
    if (fx < 0.0) {
        low = x;
    } else {
        high = x;
    }
    return bisection(low, high, f);
}

/**
 * テスト用の関数
 */
function main() {
    console.log(bisection(0, 3, x => x - 1));
    console.log(bisection(0, 3, x => x * x - 1));
}
旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法の例を JavaScript に移植しました。

このコードは、2分法によって数値解を求める関数 bisection と、そのテスト用の関数 main からなります。

bisection 関数は、下限値 low_、上限値 high_、数値解を求める対象となる関数 f を引数に取り、方程式の数値解を求める関数です。JSDocコメントにより、引数と戻り値の型、及び関数の説明が記述されています。関数内部では、2分法により数値解を求めます。まず、下限値と上限値の平均値を x とします。x を引数として関数 f を呼び出し、その戻り値を fx とします。fx が指定した精度 +1.0e-10 以下になった場合、x を数値解として返します。そうでない場合、fx が 0 より小さければ x を下限値とし、そうでなければ x を上限値とします。そして、再帰的に bisection 関数を呼び出します。

main 関数は、 bisection 関数をテストするための関数で、2つの方程式を引数に bisection 関数を呼び出し、結果をコンソールに出力します。

このコードでは、ES6 の let、テンプレートリテラル、アロー関数が使われています。また、JSDocコメントにより、関数の説明が明示的になっています。

クラス定義とインスタンス化とメンバー関数

編集
/**
 * Hello クラス
 * @class
 * @classdesc Hello クラスは、挨拶文を扱うクラスです。
 * @param {string} s - 挨拶文に含める文字列 (省略可能)
 */
class Hello {
  constructor(s = "world") {
    /**
     * 挨拶文に含める文字列
     * @type {string}
     */
    this.s = s;
  }

  /**
   * 挨拶文を文字列で表現する関数
   * @returns {string} 挨拶文の文字列
   */
  toString() {
    return `Hello ${this.s}!`;
  }

  /**
   * 挨拶文を出力する関数
   * @returns {void}
   */
  print() {
    console.log(this.s);
  }
}

/**
 * テスト用の関数
 */
function main() {
  const hello1 = new Hello();
  console.log(hello1.toString());
  hello1.print();

  const hello2 = new Hello("my friend");
  console.log(hello2.toString());
  hello2.print();

  console.log(
    `
Hello.constructor.name => ${Hello.constructor.name}
hello1 => ${hello1}
hello2.s => ${hello2.s}
`
  );
}

このコードは、JavaScriptで Hello クラスを定義し、そのクラスを使ってテストを行うためのコードです。Hello クラスは、挨拶文を扱うクラスであり、挨拶文に含める文字列を引数として受け取ります。引数が省略された場合、デフォルトで "world" という文字列を含めます。

Hello クラスには、toString() メソッドと print() メソッドがあります。toString() メソッドは、"Hello [挨拶文に含める文字列]!" という文字列を返し、print() メソッドは、挨拶文に含める文字列をコンソールに出力します。

また、main() 関数を定義し、この関数を呼び出すことで、Hello クラスを使って挨拶文を作成してコンソールに出力するテストを行うことができます。main() 関数の中では、Hello クラスのインスタンスを2つ作成し、それぞれの toString() メソッドと print() メソッドを呼び出しています。また、Hello クラスの constructor.name プロパティをコンソールに出力して、クラス名が取得できることを確認しています。