【第5回】HTML/CSS/JS入門(3)

JSにおける関数の復習とサーバーサイドの準備をします

Homeブログ一覧【第5回】HTML/CSS/JS入門(3)

今回やること

Web研究会第3回の復習かつ、今後JavaScriptを扱うにあたって関数に慣れてほしいので、関数を復習します。また、次回以降の準備としてNode.jsのインストールを行います。

関数の復習

関数宣言と関数式

JavaScriptで関数を定義する方法として、関数宣言と関数式(無名関数)があります。

関数宣言

function 関数名(引数1, 引数2, ...) {
  // 処理
}
関数宣言の例
function add(a, b) {
    return a + b;
}
console.log(add(1, 2)); // 関数を呼び出す

関数式

let 変数名 = function(引数1, 引数2, ...) {
  // 処理
};

letやconstを使って変数に関数を代入する方法です。function()のように 関数名を指定していない(省略している) ため、関数式は無名関数とも呼ばれます。

;が必要なのはlet a = 1;と同じで、変数宣言の一部として関数を定義しているためです。

関数式の例
let num = function(a, b) {
    return a + b;
};
console.log(num(1, 2)); // 関数を呼び出す

変数numfunction(a, b)という関数を代入しています。

関数宣言は宣言よりも前に呼び出すことができますが、関数式は宣言よりも前に呼び出すことができません。(スコープと巻き上げ)

アロー関数

アロー関数は、無名関数や即時関数において、より簡潔に関数を定義するための構文です。

アロー関数の書き方

function(...)の代わりに、(...) =>と記述します。

  • 引数がない場合
() => { 処理 };
  • 引数が1つの場合 ()は省略できます。
引数 => { 処理 };
  • 引数が複数の場合
(引数1, 引数2, ...) => { 処理 };
  • 処理が1行の場合 returnは省略できます。
引数 => 戻り値;
アロー関数の例
// 引数がない場合
const hello = () => {
    console.log("Hello World!");
};
hello(); // Hello World!

// 引数が1つの場合
const double = a => {
    return a * 2;
};
console.log(double(2)); // 4

// 引数が複数の場合
const sub = (a, b) => {
    return a - b;
};
console.log(sub(3, 1)); // 2

// returnが1行の場合
const sum = (a, b) => a + b;
console.log(sum(1, 2)); // 3

即時関数

即時関数とは、関数を定義すると同時に実行することができます。ただし、一度定義された関数は 再利用することができません。

即時関数を使うことで、スコープを汚染せずに新たなスコープを作成することができます。(後述します)

(function(引数1, 引数2, ...) {
  // 処理
})(引数1, 引数2, ...);

または、

(function(引数1, 引数2, ...) {
    // 処理
}(引数1, 引数2, ...));
即時関数の例
(function(a, b) {
    console.log(a + b); // 3
})(1, 2);

または(関数式を使う場合)、

const num = (function(a, b) {
    return a + b;
})(1, 2);

console.log(num); // 3

アロー関数と組み合わせることもできます。

(() => console.log("Hello World!"))();

なぜ即時関数を使うのか

以下の内容は、ES5(ECMAScript5)以前(古いJavaScript)の仕様を含むため参考程度にしてください。

JavaScriptは 関数スコープブロックスコープ の2つのスコープがあります。

スコープ

  • 関数スコープ
    • 関数内で宣言された変数は、その関数内でのみ有効です。
    • varで宣言された変数
  • ブロックスコープ
    • letconstで宣言された変数は、そのブロック{}内でのみ有効です。(ES6から)

let, const が登場したことで、こちらを用いるのが一般的となりました。 varは古いので使わないようにしましょう。

例:

if (true) {
    var a = 1; // 関数スコープ
    let b = 2; // ブロックスコープ
    const c = 3; // ブロックスコープ
}

console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined

即時関数の利用

即時関数は、コードを簡潔に書くことや同期処理中の非同期処理(ある処理が終了するのを待たずに次の処理を行う)に使われます。

// 関数の返り値を変数に代入
const a = ((x, y) => x + y)(1, 2)

// 非同期処理
(async () => {
  await ...
})()
ES5以前(古いJS)での即時関数の利用例

ES5以前のJavaScriptでは、即時関数は現在のスコープを汚染せずに新たなスコープを作成するための唯一の手段でした。

JavaScriptを書くにあたって、むやみにグローバル変数を増やしてしまうと変数の再定義により変数が上書きされ、予期せぬバグが発生する可能性があります。

  • 関数を使わない場合、グローバル変数として宣言されるため、変数が上書きされる可能性があります。
// グローバル変数として宣言
var a = 1, b = 2;
var a = 10, b = 20; // 変数の再定義により上書きされる
var result = a + b;

console.log(result()); // 30

変数abがグローバルスコープに宣言されているため、再定義により上書きされてしまいます。

  • 関数式を使った場合でもグローバルスコープに変数が残り、上書きされる可能性があります。
var cal = function() {
    var a = 1, b = 2; // 関数内でのみ有効
    return a + b;
};

var cal = () => 0; // cal関数が上書きされる

var result = cal();

console.log(cal()); // 0

今度は、変数abは関数内で宣言されているため、グローバルスコープには残りませんが、関数calが関数を格納するための変数をグローバルスコープ上に定義しているので、関数calが上書きされてしまいます。

  • 即時関数を使うことで、グローバルスコープを汚染せずに新たなスコープを作成することができます。
var result = (function() {
    var a = 1, b = 2; // 即時関数内でのみ有効
    return a + b;
})();

console.log(result); // 3

即時関数を使っているため関数の再利用はできません。 グローバルスコープ上ではresultのみが定義されているため、他の変数との衝突を避けることができます。

次回以降やることの準備

Web研究会第6回では、Webサーバーを書いてみます。準備段階として、Node.jsをインストールしておく必要があります。 Node.jsとは、JavaScriptの実行環境です。Node.jsを使うことでJavaScriptをサーバーサイドで実行することができます。

Node.jsのインストール

今回は、Node.jsのバージョン管理ツールであるnvm(Node Version Manager)を使ってNode.jsをインストールします。 参考:https://github.com/nvm-sh/nvm

curlがインストールされていない場合は、以下のコマンドでインストールします。

sudo apt -y install curl

nvmをインストールします。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash

インストールが完了したら、以下のコマンドを実行してnvmを有効にします。

source ~/.bashrc

nvmがインストールされたか確認します。

nvm --version

次に、Node.jsの最新版をインストールします。

nvm install node

インストールが完了したら、バージョンを確認します。

node --version

同時に、Node.jsのパッケージマネージャであるnpmもインストールします。

npmとはNode.jsのパッケージ管理ツールです。パッケージとはライブラリやフレームワークのことです。

ライブラリとフレームワーク

ライブラリやフレームワークとは、アプリケーションの開発において使用頻度の高い / 汎用性の高い機能の動作や処理をセットにしたものです。開発に必要な機能がまとめてあるので、ゼロから開発する必要がなくなります。

コンソール上でHello Worldを表示する

Node.jsをインストールしたら、コンソール上でHello Worldを表示してみましょう。

server.js
console.log("Hello World!");

node <ファイル名>と書いて実行することでNode.jsでファイルを実行することができます。

node server.js

コンソール上にHello World!と表示されれば成功です。

まとめ

関数は今後の講義で扱うコードの中でもよく使うため、コードを見た時に理解できるようにしておきましょう。 次回はNode.jsを使ってWebサーバーを書いてみます。Node.jsのインストールが完了していることを確認しておいてください。