JavaScriptでHello, world!
プログラミング言語を学ぶならやっぱハローワールドですよね。
目次
HTMLの作成
前述の通り、JSはHTMLから読み込む形で実装します。つまり、JSを実行するためにはまずHTMLを作成する必要があります。
今回は「ボタンをクリックしたらHello, world!と出力する」というプログラムを書いてみましょう。
まずHTMLからです。ボタンを作りたいので<button>タグを使います。idもついでに付けちゃいましょう。後でJSから操作するのが楽になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello</title>
</head>
<body>
<button id="greeting-btn">あいさつする</button>
</body>
</html>これでOKです。実際にブラウザでHTMLを開いてみましょう。今の段階ではボタンをクリックしても何も起きないと思います。
JSの作成
HTMLでボタンは実装できました。今度はJSで「ボタンをクリックしたらHello,worldと出力する」プログラムを書いていきます。
「ボタン」の取得
今のままではHTMLの「ボタン」が一体何なのかJSは理解してくれません。 まずはHTMLの中にあるボタンを明示的に取得する必要があります。HTMLファイルがあるディレクトリと同じ場所にmain.jsというファイルを作成し、以下のコードを書いてください。
const button = document.getElementById("greeting-btn");documentはHTMLのことだと思ってくれていいです。getElementById()は、引数にある名前のidを持つ要素を取得するという関数です。const button = document.getElementById("greeting-btn")と書くことで、「HTMLの中からgreeting-btnというidを持つ要素を探し、それをbuttonという名前の変数として扱う」という意味になります。こうして、ボタンをJavaScriptの変数として扱うことができました。
「ボタンがクリックされたとき、Hello,worldを出力する」機能の実装
buttonにはボタンの要素が入っています。したがって、「ボタンがクリックされた」という動作はJSとしては「変数buttonにクリックというイベントが発生した」という動作に読み替えることができます。このようなイベントを検知する関数として、addEventListener()という関数が用意されています。
function greeting() {
console.log("Hello, world!");
}
button.addEventListener("click", greeting);functionはJSにおける関数の宣言方法の1つです。JSでは関数の引数や戻り値の型も動的に決定されるため、Javaなどのように型を宣言する必要がありません。また、console.log()はJSにおける標準出力を行う関数です。JavaのSystem.out.println()と同じです。
addEventListener()はHTMLの要素に対し、「あるイベントが起きたときに、ある関数を実行する」というルールを設定することができます。第一引数には監視したいイベント、第二引数にはイベントを検知したときに実行する関数を書きます。今回の場合、検知したいイベントはクリックなので第一引数は"click"、クリックされたときにHello,worldを出力したいので第二引数はgreetingです。第二引数に関数名を入れるときに()は付けません。
HTMLからJSを読み込む
プログラムは完成しましたが、このままではHTMLがJSファイルを認識してくれません。JSのプログラムを正しく動作させるためには<script>タグを用いてHTMLから読み込んであげる必要があります。
やりかたはとっても簡単です。HTMLの<body>タグの最後に以下のコードを追記してください。
<script src="main.js"></script>これが終わったらHTMLファイルを実際にブラウザで開いてみましょう。JSの標準出力を見るためには開発者モードを使用する必要があります。(F12キーで開けます)
ボタンをクリックしたあとに開発者モードのコンソールタブにHello, world!が表示されていれば成功です!
コンソール出力ではなくHTMLを書き換えるように改良
今のままではボタンを押してもWebページは何も変化がありません。なんだか味気ないですね。そこで、コンソール出力ではなくHTMLそのものを書き換えてHello,worldを表示できるように改良します。
HTMLに見出しを追加
HTMLファイルに<h1>タグを使って見出しを追加します。現段階では内容は何も書かなくていいです。
<body>
<h1></h1> <!-- ここを追加 -->
<button id="greeting-btn">あいさつする</button>JSの書き換え
JSのプログラムも改良します。HTMLでh1タグを新しく作ったので、JS側ではボタンをクリックしたときの処理を「h1タグの要素を取得し、その内容をHello,worldに書き換える」といった処理になるようにgreeting()関数を書き換えます。
function greeting() {
const h1 = document.getElementsByTagName("h1")[0];
h1.textContent = "Hello, world!";
}TIP
getElementsByTagName()関数はgetElementById()のタグ版です。この関数を使えば、idが無くてもタグの名前で要素を検索・取得することができます。
ただし、getElementsByTagName()は検索したタグの要素を全て取得し、HTMLCollectionという配列に似た形式のデータを返します。今回のh1タグの要素は1つしかありませんが、それでもサイズが1の配列として返ってきます。
サンプルコードのようにgetElementsByTagName("h1")[0]と書くことで、検索した要素の中で一番はじめのものを指定して取得することができます。
WARNING
class名で要素を検索できるgetElementsByClassName()という関数もありますが、これも検索に一致するclassの要素を全て取得するため、getElementsByTagName()と同様に扱ってあげる必要があります。
ここまでできたらWebページを更新し、再度ボタンをクリックしてください。画面が変わったら成功です!
余談
DOM操作とは?
今回行った「HTMLの要素を取得してその内容を書き換える」といった処理は、一般的にDOM操作と呼ばれます。まずはDOMから解説していきます。
JavaScriptはブラウザ上で動く言語ですが、HTMLの内容をそのままJavaScriptのデータ構造として扱うことができません。 ブラウザは賢いので、JavaScriptがHTMLを操作できるよう、ブラウザ自身がいい感じにHTMLを変換して、JavaScriptが理解できるデータ構造にしてくれます。この「いい感じ」なデータ構造をDOM(Document Object Model)といいます。
例えば、次のHTMLがあるとします。
<body>
<h1>タイトル</h1>
<button>ボタン</button>
</body>ブラウザは、このHTMLをおおまかに次のような階層構造に変換します。木構造の形式を取ることから、このデータ構造はDOMツリーと呼ばれます。
document
└── html
├── head
└── body
├── h1
└── buttondocument.getElementById()などを使うと、このDOMツリーの中から特定の要素を探すことができます。 また、取得した要素のtextContentを変更すると、ブラウザに表示される内容も変化します。
const h1 = document.getElementsByTagName("h1")[0];
h1.textContent = "Hello, world!";このプログラムで書き換えているのはHTMLそのものではなく、あくまでブラウザが表示しているDOMです。
DOM操作を使うと、文字の変更以外にもさまざまなことができます。
- 要素の内容を書き換える
- 新しい要素を追加する
- 不要な要素を削除する
- classや属性を変更する
- 入力フォームに書かれた値を取得する
JavaScriptを使って動きのあるWebページを作るときには、このDOM操作をたくさん使います。JavaScriptはDOM操作をするために作られた言語といっても過言です。
querySelector()を使って要素を取得する
HTMLの要素を取得する関数には、これまで使ったもの以外にquerySelector()があります。
querySelector()では、CSSと同じ書き方で取得したい要素を指定できます。
idで取得する
idを指定するときは、id名の前に#を付けます。
<button id="greeting-btn">あいさつする</button>const button = document.querySelector("#greeting-btn");これは、次のコードとほぼ同じ意味です。
const button = document.getElementById("greeting-btn");classで取得する
classを指定するときは、class名の前に.を付けます。
<p class="message">こんにちは!</p>const message = document.querySelector(".message");タグ名で取得する
タグを指定するときは、タグ名をそのまま書きます。
const heading = document.querySelector("h1");今回作ったプログラムも、querySelector()を使うと次のように書けます。
const button = document.querySelector("#greeting-btn");
function greeting() {
const heading = document.querySelector("h1");
heading.textContent = "Hello, world!";
}
button.addEventListener("click", greeting);querySelector()は、条件に一致する要素のうち最初の1つを返します。
条件に一致するすべての要素を取得したい場合は、querySelectorAll()を使います。
<p class="message">1つ目</p>
<p class="message">2つ目</p>
<p class="message">3つ目</p>const messages = document.querySelectorAll(".message");
console.log(messages[0].textContent); // 1つ目
console.log(messages[1].textContent); // 2つ目
console.log(messages[2].textContent); // 3つ目querySelector()はid・class・タグのどれでも検索できるのが強みです。どっちを使っても構いません。好みでどうぞ。
アロー関数
JavaScriptには、関数を宣言する方法がいくつかあります。
これまで使ったgreeting()関数は、functionを使って次のように宣言しました。
function greeting() {
console.log("Hello, world!");
}
button.addEventListener("click", greeting);JavaScriptでは、これに近い処理をアロー関数を使って書くこともできます。
const greeting = () => {
console.log("Hello, world!");
};
button.addEventListener("click", greeting);=>の見た目が矢印に似ているため、アロー関数と呼ばれています。
基本的な書き方は次の通りです。
const 関数名 = (引数) => {
// 実行する処理
};Javaのメソッドとは違い、JavaScriptでは関数そのものを変数に代入できます。
上の例では、作成した関数をgreetingという名前の変数に代入しています。そのため、通常の関数と同じように次のコードで実行できます。
greeting();引数を受け取るアロー関数
アロー関数でも引数を受け取れます。
const greeting = (name) => {
console.log(`こんにちは、${name}さん!`);
};
greeting("田中");実行結果は次のようになります。
こんにちは、田中さん!複数の引数を受け取りたい場合は、カンマで区切ります。
const add = (a, b) => {
console.log(a + b);
};
add(2, 3);戻り値のあるアロー関数
returnを使って値を返すこともできます。
const add = (a, b) => {
return a + b;
};
const result = add(2, 3);
console.log(result);処理がreturnだけの場合は、次のように短く書くこともできます。
const add = (a, b) => a + b;{}を省略した場合は、計算結果が自動的に戻り値になります。
最初のうちは、処理の内容が分かりやすい次の書き方を使っても問題ありません。
const add = (a, b) => {
return a + b;
};addEventListener()の中に直接書く
今回のプログラムでは、ボタンがクリックされたときに実行する関数を別に宣言していました。
function greeting() {
const heading = document.querySelector("h1");
heading.textContent = "Hello, world!";
}
button.addEventListener("click", greeting);この関数を他の場所で使わない場合は、アロー関数をaddEventListener()の第二引数に直接書けます。
button.addEventListener("click", () => {
const heading = document.querySelector("h1");
heading.textContent = "Hello, world!";
});このアロー関数には名前がありません。このような名前のない関数を無名関数と呼びます。
処理の流れは次の通りです。
buttonのクリックを監視する- ボタンがクリックされる
- 第二引数に書いたアロー関数が実行される
h1の内容がHello, world!に変わる
クリック時の処理をその場にまとめられるため、イベント処理ではこの書き方がよく使われます。
イベントの情報を受け取る
addEventListener()に渡した関数は、発生したイベントの情報を引数として受け取れます。
button.addEventListener("click", (event) => {
console.log(event);
});引数名は自由に決められますが、eventまたはeという名前がよく使われます。
button.addEventListener("click", (e) => {
console.log(e);
});クリックされた要素はevent.targetで確認できます。
button.addEventListener("click", (event) => {
console.log(event.target);
});今回の場合、コンソールにはクリックされたbutton要素が表示されます。
DANGER
第二引数に関数を渡すときは、関数をその場で実行しないように注意してください。
// OK: ボタンがクリックされたときに実行される
button.addEventListener("click", greeting);
// NG: ページを読み込んだ時点で実行されてしまう
button.addEventListener("click", greeting());greetingは関数そのものを表します。 greeting()は、その関数をすぐに実行するという意味です。