Webデザイン学科
授業資料

JavaScript演習
コールバック関数とclass

概要解説

JavaScript の根幹であるコールバック関数の解説と class について解説します。

  • 欠席者_SSG で EC サイト発表
  • 後期選択科目申し込み書配布(8/25 持参)

内容

  • 関数の復習
  • メソッド
  • 引数にオブジェクトを渡す
  • 無名関数(匿名関数)
  • オブジェクト
  • JavaScript クイズ結果

授業資料

関数

戻り値が無い関数は、処理の結果を関数が決めます。
戻り値がある関数は、処理の結果を関数外で決めます。

//戻り値を返さない関数
function makeJuice(fruits) {
  alert(fruits + "ジュース"); //出力の仕方は関数が決める。
}
makeJuice("オレンジ");

//戻り値を返す関数
let makeJuice = function(fruits) {
  return fruits + "ジュース"; //戻り値
}
console.log(makeJuice("バナナ"); //出力の仕方は関数外で決める。

関数の定義・関数式・関数の実行の関数名 makeJuice は同じです。
ということは中身は同じだという理屈がわかりますか?
makeJuice は function オブジェクトとなります。

[演習]関数定義と実行の復習

引数に(“醤油”)と渡すと console に「醤油ラーメン」と表示される関数を、① 関数定義 ramenMaker と、② 関数式 makeNoodle で作って、実行させてください。

メソッド

オブジェクトの中に、関数を設定することができます。
この関数のことをメソッドといいます。

const ramen = {
	name: '寿がきや',
	color: 'white',
	fn: function (taste = 'ノーマル') {
		console.log(this.name + 'ラーメン' + taste);
	}
};
ramen.fn();
ramen.fn('スペシャル');

関数はオブジェクト(function オブジェクト)

JavaScript で扱う値は、全てオブジェクトとして扱うことができます。
そして関数もまた、オブジェクトです。

//関数の定義
function makeJuice(fruits) {
	console.log(fruits + 'ジュース');
}

//プロパティjapaneseの設定
makeJuice.japanese = 'ジューサー';

//関数式(メソッドの設定)
makeJuice.hello = function () {
	console.log('こんにちは');
};

登録したプロパティ japanese やメソッド(関数)hello を見ることができます。

console.dir(makeJuice);
console.log(makeJuice.japanese);
//オブジェクト内の関数は、メソッドという
//メソッド(関数)の実行
makeJuice.hello();
makeJuice('いちご'); //いちごジュース
makeJuice.hello(); //こんにちは
makeJuice('スイカ').hello(); //スイカジュース そしてエラー

すでに「スイカジュース」が出力。
スイカジュースには、hello メソッドが設定されていないためエラーとなる。

引数にオブジェクトを渡す

引数には、オブジェクトを読み込ませることができます。

基本は、下記で集計していました。問題によっては、◎(大正解)があった問題もあります。

const fruits = { name: 'マンゴー', price: 450, amount: '200ml' };
//関数の定義①
function makeJuice(material) {
	console.log(material.name);
	console.log(material.price);
	console.log(material.amount);
}

//関数の実行
makeJuice(fruits);

コールバック関数

関数がオブジェクトであるのであれば、他の関数を引数として読み込めます
この引数で渡される関数のことをコールバック関数といいます。

const fruits = { name: 'マンゴー', price: 450, amount: '200ml' };
//関数の定義①
function makeJuice(func, mat) {
	func(mat);
}
//関数の定義②
function juicer(materials) {
	console.log(materials.name + 'ジュース');
}
//関数の実行
//第1引数が関数、第2引数がオブジェクト
makeJuice(juicer, fruits);

[演習]コールバック関数

関数 ramenMaker にトッピングをするための関数 topping を第 2 引数として、コールバック関数を読み込ませて、関数 ramenMaker を実行すると、コンソールに「醤油ラーメンバターコーン」と表示されるようにしてください。

//↓をベースに編集していく
function ramenMaker(soup) {
	console.log(soup + 'ラーメン');
}

function topping(add) {
	return add;
}

ramenMaker();

無名関数(匿名関数)

関数名を記述せずに定義した関数を無名関数(匿名関数)といいます。

function(fruits) {
  return fruits + "ジュース";
}

どこかで見たことがあるはずです。関数式の変数(関数名)に代入する値です。
その他、element.addEventListener( "event", function () {処理;})にも使われています。
無名関数は、一度しか呼び出されないようなケースを使い、複数回呼び出す場合は、関数式にしたり、関数宣言をして名前付き関数にします。

オブジェクト

オブジェクトでは、「データ」と「データを操作する方法(処理)」を、ひとまとめにすることができます。

<p id="result"></p>

<script>
	const demaeicchou = {
		name: '出前一丁',
		soup: '醤油',
		preview: function () {
			const area = document.querySelector('#result');
			area.innerHTML = `${this.name}は、${this.soup}ラーメンです。`;
		}
	};
	demaeicchou.preview();
	//出前一丁は、醤油ラーメンです。
</script>

オブジェクトの操作

書き換えや追加、削除が簡単にできます。

demaeicchou.soup = 'とんこつ';
demaeicchou.preview = function () {
	const area = document.querySelector('#result');
	area.innerHTML = `${this.name}は、${this.soup}ラーメンではありません。`;
};
delete demaeicchou.name;

demaeicchou.preview();
//undefinedは、とんこつラーメンではありません。

この手軽さが、メリットでもありデメリットでもあります。
「カプセル化」することで書き換えがされずに、ひな形としても利用できるようにするのがクラスです。

クラスの基本

他のデータを取得できるひな形を作成します。それがクラスです。
クラスには、関数と同じように、クラスの定義とクラス式がありますが、let や var を利用すると class 自体を書き換えられてしまうので、わざわざ「カプセル化」しているのに、意味がありません。よって一般的にクラスの定義を利用します

※クラス名の命名規則としては大文字始まりです。

コンストラクタ

クラスでは、オブジェクトの生成を行うとき(new すると)に実行するメソッドをコンストラクタ(constructor=構成する)といいます。
メソッドの定義もできます。

<div id="app"></div>
class InstantNoodle {
	constructor(ramen, taste) {
		this.name = ramen;
		this.soup = taste;
		this.area = document.getElementById('app');
	}
	descript() {
		this.area.innerHTML = `${this.name}は、${this.soup}です。`;
	}
}

インスタンス

クラスからオブジェクトを生成する処理をインスタンス化と言い、生成されたオブジェクトのことをインスタンスと呼びます。
インスタンス化には new 演算子を使います。

const soltRamen = new InstantNoodle('サッポロ一番塩', '塩');
soltRamen.descript();
const demaeicchou = new InstantNoodle('出前一丁', '醤油');
console.log(demaeicchou);

クラスの継承

既存のクラスを継承(引き継ぐ)ことで、既存のクラスの機能を利用して、少し機能の異なるクラスを新たに生成する記法です。
再利用することで、効率化などができます。

class Special extends InstantNoodle {
	constructor(ramen, taste) {
		super(ramen, taste);
	}
	descript() {
		const pElm = document.createElement('p');
		pElm.innerHTML = `${this.name}は、${this.soup}です。`;
		this.area.appendChild(pElm);
	}
}
const specialNoodle = new Special('50周年', '塩/醤油');
specialNoodle.descript();

Demo とオブジェクト指向

class を使った簡単な box を作ってみましょう。

ダミー商品

<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>box</title>
		<style>
			.goods {
				display: flex;
			}
		</style>
	</head>

	<body>
		<h1>クラスDemo</h1>

		<div class="goods"></div>
		<script src="./script.js"></script>
	</body>
</html>
const goodsDatas = [
	{
		name: '商品1',
		text: '商品1の説明分です。',
		img: 'goods.webp'
	},
	{
		name: '商品2',
		text: '商品2の説明分です。',
		img: 'goods.webp'
	},
	{
		name: '商品3',
		text: '商品3の説明分です。',
		img: 'goods.webp'
	}
];

class Box {
	constructor(datas) {
		this.area = document.querySelector('.goods');
		this.box;
		for (let data of datas) {
			this.box = document.createElement('div');
			this.box.classList.add('box');
			this.box.innerHTML = `<h2>${data.name}</h2>
<img src="${data.img}" alt="${data.name}">
<p>${data.text}</p>
`;
			this.area.appendChild(this.box);
		}
	}

	changeColor(color) {
		this.area.addEventListener('click', function () {
			this.style.color = color;
		});
	}
}

const boxObject = new Box(goodsDatas);
boxObject.changeColor('red');

このような「オブジェクトとそのデータに対する演算をひとまとめにするプログラミング手法」をオブジェクト指向と言い、現在のプログラミング手法の主流となっています。

エクスポートとインポート

クラスや関数が増えてくると、複数のファイルに分割して「モジュール[部品]」として、export(エクスポート[書き出し])や import(インポート[読み込み])して利用します。
この仕組みをモジュールシステムといいます。
モジュールシステムには、ES Modules(ESM)と CommonJS(CJS)があります。
今回は、JavaScript でも Node.js でも利用できる ESM を使って演習をします。

ES Module の有効化

//HTMLファイル内に記述する時
<script type="module">
  /* ES Modulesが有効になる */
</script>

//JavaScriptファイルを読み込む場合
<script type="module" src="./js/script.js(パス)"></script>

エクスポート

ES Modules のエクスポート(外部への機能の露出)には、次の 3 つの方法があります。

  • 名前付きエクスポート
  • デフォルトエクスポート
  • モジュールの集約

export.js

const foo = 'foo';

// 宣言済みのオブジェクトを名前つきエクスポートする
export { foo };

// 宣言と同時に名前つきエクスポートする
export function bar() {}

インポート

export した機能を使うには、インポートを行います。インポートの方法には、2 種類あります。

  • 静的インポート(Static Imports)
  • 動的インポート(Dynamic Imports)

import.js

// 名前つきエクスポートされたfooとbarをインポートする
import { foo, bar } from './export.js';

console.log(foo); // => "foo"
console.log(bar); // => "bar"

index.html

<script type="module" src="./import.js"></script>

JavaScript クイズ結果

  • ○:正解
  • △:もう少しで正解
  • ×:動かず

TOP9

全14 回の授業での成績 TOP9 です。

  • 3【◎1-○5-△3】
  • 5【◎1-○9-△1】
  • 6【◎2-○11-△1】
  • 9【◎2-○8-△2】
  • 11【◎2-○8-△1】
  • 13【◎1-○7-△1】
  • 16【◎1-○13】
  • 17【◎2-○11-△1】
  • 18【◎2-○10-△1】

2022-08-04
Hideo kawaguchi