JavaScriptを使ってゲームを作成するのが好きです。@It_is_Rです。
JavaScriptはWebページに動きを出すのによく使われ、ブラウザゲームなども作ることができます。
今回は JavaScript について、初心者の人にも分かりやすく、丁寧に解説していきます。
JavaScript と EcmaScript
JavaScript は、主にWeb開発などで使われるプログラミング言語です。
もちろん、ゲームなどを作成することもできます。
また、 EcmaScript とは、 Ecma International という団体が標準化した JavaScript の規格です。
2019年7月8日現在の最新バージョンは、 ECMAScript2019 です。
これは10番目に出た言語仕様なので、ECMAScript10(ES10)とも呼ばれます。
2015年6月にES2015(ES6)が公開され、その後毎年新しいバージョンがリリースされています。
このES2015(ES6)では、それまでのバージョンと比べて大きな変更があり、様々な機能が追加されました。
ES2015(ES6)での大きな仕様変更
前述の通り、ES2015(ES6)では大きな仕様変更がありました。
つまりES2015(ES6)はこれまでのJavaScriptの記法と大きく異なります。
もともとvarのみだった変数宣言も、新しく追加されたlet, constにより、その場に応じた宣言が可能になりました。
またクラス構文の追加により、これまで扱いにくいクラスの作成方法を使っておりましたが、これも直感的に分かりやすくなりました。
その他、アロー関数など、様々な機能が追加されております。
開発環境を整える
JavaScript での開発には、 Webブラウザとテキストエディタが必須になります。
今回は Google Chrome を使用します。長い間ブラウザの更新をしていない場合は、対応していないことがあるので、最新のものを用意しておいてください。
テキストエディタは、 Atom や Sublime Text 、 Visual Studio Code 、 Vim などが有名です。
こちらの記事も参考にしてください。
WEB開発で使えるフリーのテキストエディタ、厳選ベスト3!
Google Chrome の コンソール ( Console ) について
Console.log() などの命令を使った場合や、簡単なプログラムを実行したい場合は、 Google Chrome の Console を使うと便利です。
Chrome を開いた後、適当な箇所で右クリックします。
表示されたメニューから、「検証」を選択すると、そのサイトのソースが表示されます。
最後に Console タブを選択することによって、 Google Chrome の Console を使うことができるようになります。
HTML の書き方
まずは HTML ファイルを作っていきます。
index.html というファイルを作成し、以下の内容で保存しましょう。
index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>サンプル</title> </head> <body> <script src="script.js"></script> </body> </html>
bodyタグの一番下で、scriptタグを使い、外部ファイルを読み込む形です。
HTML ファイルを作ったら、同じディレクトリに script.js というファイルも作っておいてください。
コメントを使う
プログラムを作るとき、ソース内に覚えとして、メモをしておきたい場合があります。
また、複数人で開発を行う場合、メモを入れて、どこがどの様な動きをしているか、他のプログラマーに伝えたいこともあります。
その場合に使うのが、コメントです。
コメントは実行結果に反映されないので、日本語での入力も可能になります。
一行のコメント
一行のコメントを使いたい場合、 // を使います。
script.js
//コメントを入力
この様に、先頭に // をつけることによって、プログラムの実行結果に反映されない文字を入力することができます。
複数行のコメント
複数行のコメントを使いたい場合、 /* と */ でコメントを挟みます。
script.js
/*コメントを 入力*/
文字を表示する
文字列を表示する方法です。
この後紹介する変数と区別をつける為、文字列は’ ‘、もしくは” “で挟むようにします。
コンソールに文字列を表示する
コンソールに文字列を表示するには、以下のようにします。
実行結果は上記の方法で確認することができます。
script.js
console.log('Hello World!');
アラートを表示する
アラートを表示する方法もあります。
script.js
alert('Hello World!');
演算
演算の前に、後ほど解説する変数について軽く触れておきましょう。
変数は、データを入れておく為の箱です。
例えば、 num という変数に 3 という数値を入れておくというかたちです。
変数にデータを入れることを、代入といいます。
代入には = を使います。
下の例では、 num という変数に、 3 を代入するという意味になります。
script.js
num = 3;
算術演算
算術演算子には、以下のものがあります。
演算子 | 使用例 | |
---|---|---|
加算 | + | a = b + c |
減算 | – | a = b – c |
乗算 | * | a = b * c |
除算 | / | a = b / c |
剰余 | % | a = b % c |
べき乗 | ** | a = b ** c |
インクリメント | ++ | a++, ++a(1足す) |
デクリメント | −− | a−−, −−a(1引く) |
script.js
let x = 0; x = 2 + 9; console.log(x);
実行結果
11
インクリメント、デクリメント
インクリメントは、 1 ずつ足す
デクリメントは、 1 ずつ引く
前置、後置の違いは、以下の様になります。
let については、変数の宣言の項目をご覧ください。
script.js
let x1 = 0, x2 = 0; let y1 = 0, y2 = 0; x1 = x2++; y1 = ++y2; console.log(x1); console.log(y1); console.log(x2); console.log(y2);
実行結果
0 1 1 1
1〜4行目で、使いたい変数全てに 0 を代入します。
6〜7行目で、インクリメントを使い、前置、後置の違いを確かめます。
9〜12行目で、コンソールに表示します。
後置の場合、右側の変数に1が足されてから代入され、前置の場合、右側の変数に数値が1が足される前に代入されていることが分かります。
比較演算
比較演算子は以下のものが使えます。
演算子 | 使用例 | |
---|---|---|
等しい | == | a == b |
等しくない | != | a != b |
厳密に等しい | === | a === b |
厳密に等しくない | !== | a !== b |
以上 | >= | a >= b |
より大きい | > | a > b |
代入演算
代入演算子を使うことで、演算の記述が楽になります。
演算子 | 使用例 | 意味 | |
---|---|---|---|
加算代入 | += | a += b | a に b を加算 ( a = a + b ) |
減算代入 | -= | a -= b | a から b を減算 ( a = a – b ) |
乗算代入 | *= | a *= b | a に b を乗算 ( a = a * b ) |
除算代入 | /= | a /= b | a に b を乗算 ( a = a / b ) |
剰余代入 | %= | a %= b | a を b で割った余り ( a = a % b ) |
べき乗代入 | **= | a **= b | a の b 乗 ( a = a ** b ) |
ビット演算
ビット演算では、ビット単位での演算を行うことができます。
ゼロ埋め右シフト>>>a >>> b-24 << 2 ならば、 1073741818 を返す。
演算子 | 使用例 | 意味 | |
---|---|---|---|
ビット論理積 ( AND ) | & | a & b | 1 & 1 ならば、 1 を返す。 |
ビット論理和 ( OR ) | | | a | b | 1 | 1 ならば、 1 を返す。 |
ビット排他的論理和 ( XOR ) | ^ | a ^ b | 1 | 0 ならば、 1 を返す。 |
ビット否定 ( NOT ) | ~ | ~a | ~1 ならば、 -2 を返す。 |
左シフト | << | a << b | 24 << 2 ならば、 96 を返す。 |
符号維持右シフト | >> | a >> b | 24 >> 2 ならば、 6 を返す。 |
ビット論理積 ( AND )
まず、ビット論理積 ( AND )について、解説します。
ビット論理積は、 a & b と表すことができます。
まず、下の例を見てください。
script.js
console.log(25 & 23);
実行結果
17
これは、 25 と 23 をビットに変換したときに、両方の数値が 1 だった場合のみ 1 という規則に沿っていきます。
実際にやってみましょう。
まず、 25 と 23 を2進数に変換します。
11001
10111
両方の数値が 1 だった場合のみ 1 ですので、こうなります。
10001
これを再び10進数に変換すると、 17 になり、これが実行結果となります。
ビット論理和 ( OR )
ビット論理和も、ビット論理積と同様に、ビットに変換してから演算されます。
script.js
console.log(25 | 23);
実行結果
31
ビット論理和 ( OR )では、両方の数値、もしくは片方の数値が 1 だったとき 1 という規則で返されます。
先ほどと同じ様に、実際にやってみましょう。
11001
10111
両方の数値、もしくは片方の数値が 1 だったとき 1 ですので、こうなります。
11111
これを10進数に変換すると、 31 になります。
ビット排他的論理和 ( XOR )
ビット排他的論理和 ( XOR )についてです。
script.js
console.log(25 ^ 23);
実行結果
14
排他的論理和では、双方の値が異なる場合に 1 、それ以外の場合は 0 が返されます。
11001
10111
双方の値が異なる場合に 1 、それ以外の場合は 0 ですのでこうなります。
01110
10進数に変換すると、 14 です。
シフト
シフトは、ビットを左右にずらすことです。
例えば、 11001 を左に 2 ビットシフトすると 1100100 となります。
符号維持右シフトとゼロ埋め右シフトの違い
符号維持右シフトとゼロ埋め右シフトは、負数でない限り同じ結果を得ることができます。
script.js
console.log(5 >> 2); //符号維持右シフト console.log(5 >>> 2); //ゼロ埋め右シフト
実行結果
1 1
しかし、負数の場合は結果が異なります。
script.js
console.log(-5 >> 2); //符号維持右シフト console.log(-5 >>> 2); //ゼロ埋め右シフト
実行結果
-2 1073741822
ゼロ埋め右シフトでは、とてつもない値になっていることが分かります。
では、なぜこの様な値になるのでしょうか?
JavaScript では、10進数を32ビットの2進数に変換して演算が行われます。
-5 の2進数は32ビットの場合、 11111111111111111111111111111011 となります。
2 進数には、符号ビットと呼ばれるものがあります。
最上位ビット( MSB ) 、つまり、一番左側のビットが、符号ビットと呼ばれるものです。
この値が 0 ならば負数でない数、 1 ならば負数となります。
符号維持右シフトでは、ここで符号ビットが維持されるのですが、ゼロ埋め右シフトでは、 0 を左に詰めます。
これを右に 2 シフトすると、 00111111111111111111111111111110 となります。
これを10進数に変換すると、 1073741822 となるわけです。
2進数でマイナスの値を表す
2進数の負数の表し方への理解が深まる様、ここでマイナスへの変換方法を見てみましょう。
5 を -5 に変換する作業を2進数で行なってみましょう。
5 の2進数は、 101 です。これを32ビットで表すと、 00000000000000000000000000000101 となります。
マイナスに変換する場合、 0 と 1 を反転させた後に、 1 を足します。
00000000000000000000000000000101
反転させる。
11111111111111111111111111111010
1 を足す。
11111111111111111111111111111011
これが、 -5 の2進数です。
論理演算
論理演算は、ブール値( Boolean value )を用いた演算を行います。
ブール値については、変数の項目をご覧ください。
演算子 | 使用例 | 意味 | |
---|---|---|---|
論理積 ( AND ) | && | true && true | 双方が true ならば true を返す。それ以外ならば false |
論理和 ( OR ) | || | true || false | 双方、もしくは片方が true ならば true を返す。それ以外ならば false |
論理否定 ( NOT ) | ! | !a | true の場合 false 、 false の場合 true |
文字列演算
script.js
console.log('こんにちは。' + 'こんばんは。');
実行結果
こんにちは。こんばんは。
変数を使う
変数は、データを入れておく箱のようなものです。
箱と言われてもよく分からないと思いますので、実際の使用例で確認してみましょう。
script.js
var name = 'Pochi'; console.log(name);
実行結果
Pochi
上記の例ですと、 var が変数宣言、 name が変数名、 Pochi が値となります。
以下で詳しく解説していきます。
変数を宣言する
変数を使用するには、まず変数の宣言を行うことにより、バグを防ぐことができるようになります。
以下に変数の宣言方法を記述します。
var
従来の JavaScript の宣言方法です。
script.js
var num; num = 6; console.log(num);
実行結果
6
1行目 : var で num という変数の宣言。
2行目 : num に 6 という数値を代入。
3行目 : コンソールに、 num に代入された値を出力。
また、 1行目 の、 var num; と、 2行目の num = 6; を組み合わせることもできます。
その場合、以下の様になります。
script.js
var num = 6; console.log(num);
どちらでも同じ出力結果を得られますが、後から紹介したものの方が、ソースの量が少なくてすむので、こちらを使うことをお勧めします。
let
ECMAScript2015 ( ES6 )からは、 var の代わりに let で宣言することができるようになりました。
使い方は var と同じですが、 var と let では、意味が異なります。
違いについては後ほどスコープの項目で解説します。
script.js
let num = 6; console.log(num);
実行結果
6
const
const は定数を宣言する時に使います。
定数は、後から変更しない変数と思えばいいでしょう。
script.js
const NUM = 6; console.log(NUM);
実行結果
6
定数では、変更可能な変数と区別するために、定数名を全て大文字で記述します。
変数の型
JavaScript では、変数に値を代入した時点で、変数の型が決まります。
では、それぞれの型の違いを見ていきましょう。
型を調べる場合は、 typeof という命令を使います。
script.js
let str = 'こんにちは'; let num = 6; let existence = true; console.log(typeof str); console.log(typeof num); console.log(typeof existence);
実行結果
string number boolean
1行目では、 str という変数に、「こんにちは」という文字列を代入しています。
2行目では、 num という変数に、「6」という数値を代入しています。
3行目では、 existence という変数に、「true」という真理値(真偽値)を代入しています。
まだ、真理値について学んでいないので、ここで軽く学んでおきましょう。
真理値は、 true , false のどちらかを代入することができます。
正しい ( true ) か、正しくない ( false ) かの判定に使用されます。
5〜7行目で、それぞれの変数の型を判定しています。
str は string (文字列)、 num は number ( 数値 )、 existence は boolean ( 真理値 )であることが分かります。
ここまでで学習した内容であれば、 typeof で型判定することが可能ですが、型判定がうまくいかないものもあるので、その点は注意が必要です。
スコープ
スコープとは、変数の有効範囲のことです。
ブロック
ブロックは、ソースをグループ化するときに使うことができます。
script.js
{ let str = 'こんにちは'; console.log(str); }
実行結果
こんにちは
この様に、 { } で挟むと、その部分が一つのブロックとなります。
また、後々紹介する、 for 、 while 、 if なども、ブロックとなります。
ブロックスコープ
ブロックスコープとは、ブロックでのスコープ、つまり、ブロック内でのみ変数が有効になることです。
変数の宣言には、もともと var を使っていましたが、 ECMAScript6 からの let により、ブロックスコープを使うことが可能になりました。
script.js
{ var str_var = 'こんにちは'; let str_let = 'こんにちは'; console.log(str_var); console.log(str_let); } console.log(str_var); console.log(str_let);
実行結果
こんにちは こんにちは こんにちは Uncaught ReferenceError
2〜3行目 : let と var をそれぞれ使い、 それぞれの変数に、「こんにちは」という文字列を代入しています。
4〜5行目 : それぞれ変数に代入した文字列をコンソールに表示しています。
7〜8行目 : ブロックの外側で、 それぞれの変数を使ってみます。
4〜5行目と、7行目で変数を使用した場合はエラーになりませんが、8行目で変数を使った場合はエラーになりました。
ブロック内で let を使用して宣言した変数は、そのブロック内でのみ有効であることが分かります。
また、 var を使って宣言した変数は、そのブロックの外でも有効になります。
関数スコープ
関数スコープは、変数の関数内での有効範囲です。
関数についてはまだ紹介していないのですが、ここで少しだけ触れてみましょう。
関数スコープでは、 let で宣言した変数、 var で宣言した変数共に、有効範囲が有効になります。
script.js
function testFunc() { var x = 2; console.log(x); } testFunc(); console.log(x);
実行結果
2 Uncaught ReferenceError
1〜4行目が、関数です。
それを6行目で呼び出しています。
7行目で、関数内の x を使おうとしていますが、これはエラーになります。
関数については後ほど解説します。
今は function testFunc() { } の中のみで変数が有効になっているということだけ、理解しておいてください。
ローカル変数とグローバル変数
ローカル変数は、関数やブロック内で宣言され、その関数やブロックの中でのみ有効の変数です。
グローバル変数は、関数やブロック外で宣言され、どこからでも使用できる変数です。
また、宣言をしなかった場合、その変数はグローバル変数となります。
*この方法は、後術する strict モードではエラーになります。
script.js
function testFunc() { str = 'グローバル変数'; console.log(str); } testFunc(); console.log(str);
実行結果
グローバル変数 グローバル変数
テンプレートリテラル
テンプレートリテラルも、 ECMAScript6 から使用可能となりました。
基本的な使い方は、 「 ` ` 」で、を文字列を挟みます。
script.js
console.log(`テンプレートリテラル`);
実行結果
テンプレートリテラル
改行
テンプレートリテラルを使うと、改行も楽になります。
script.js
console.log(`テンプレート リテラル`);
実行結果
テンプレート リテラル
文字列内で、変数を使う
文字列内で変数を使う場合は、 ${ 変数名 } を使います。
script.js
let x = 6; console.log(`値は${x}です。`);
実行結果
値は6です。
こうすることで、演算を使わずにすみます。
オブジェクト
オブジェクトは、「物」、「物体」、「対象」などの意味を持ちます。
プログラミングを学び始めたばかりの人が、理解しがたい部分だと思います。
では、オブジェクトについて解説していきたいと思います。
オブジェクトとは
先ほど、オブジェクトは「物」という意味があると書きました。
物には様々な特徴があります。大きさや、色、形、重さなどです。
JavaScript では、その様なオブジェクトの特徴(特性)を、プロパティによって表すことができます。
オブジェクトとプロパティ
プロパティを使うことで、オブジェクトの特徴(特性)を表すことができます。
ここで実際に使って見ましょう。
ゲームに例えてみましょう。
主人公は、ドラゴンを倒すための冒険へ旅立ちます。名前は「二郎」です。
ここで、二郎の状態を示します。
HP : 162
MP : 67
ATK(攻撃力) : 132
DEF(守備力) : 110
こんな感じでしょうか。
では、「二郎」というオブジェクトを作成してみましょう。
HP , MP , ATK , DEF はプロパティです。
script.js
let jiro = new Object(); jiro.hp = 162; jiro.mp = 67; jiro.atk = 132; jiro.def = 110; console.log(`二郎の攻撃力は${jiro.atk}だ!!`);
実行結果
二郎の攻撃力は132だ!!
また、次の様に書くこともできます。
script.js
let jiro = { hp: 162, mp: 67, atk: 132, def: 110 } console.log(`二郎のHPは${jiro.hp}だ!!`);
実行結果
二郎のHPは162だ!!
制御構文
制御構文を使うことにより、プログラムの流れを変えることができます。
以下で詳しく見ていきましょう。
if , if-else
if文 は、ある条件によって分岐させる命令です。
下の例は if文 により、 x に 6 が代入されている場合のみ「数値は6です」と表示させるものです。
script.js
let x = 6; if (x === 6) { console.log('数値は6です。'); }
実行結果
数値は6です。
else を使うことで、その条件が当てはまらない場合の処理を書くことができます。
script.js
let x = 5; if (x === 6) { console.log('数値は6です。'); } else { console.log('数値は6ではありません。'); }
実行結果
数値は6ではありません。
else の後に if を繋げることで、複数の条件を重ねることができます。
script.js
let x = 5; if (x === 6) { console.log('数値は6です。'); } else if (x === 7) { console.log('数値は7です。'); } else { console.log('数値は6でも7でもありません。'); }
実行結果
数値は6でも7でもありません。
switch
if else を繋げても問題はないのですが、条件が多い場合は switch を使った方が楽になります。
script.js
let x = 5; switch (x) { case 3: console.log('数値は3です。'); break; case 4: console.log('数値は4です。'); break; case 5: console.log('数値は5です。'); break; default: console.log('数値はいずれにも該当しません。'); break; }
実行結果
数値は5です。
for
for は、繰り返しを行う命令です。
script.js
for (var i = 1; i <= 5; i++) { console.log(`${i}回目`); }
実行結果
1回目 2回目 3回目 4回目 5回目
for-in
for-in では、オブジェクトのプロパティに対しての繰り返しを行います。
for (プロパティ(変数) in オブジェクト) { } という形になります。
プロパティ(変数)の部分には、対象とするオブジェクトのプロパティを代入したい変数、オブジェクトの部分には対象とするオブジェクト名を入力します。
オブジェクトについての項目で使用した、二郎を例にしたサンプルです。
二郎の強さを出力します。
script.js
let jiro = { hp: 162, mp: 67, atk: 132, def: 110 } for (var prop in jiro) { console.log(`${prop} ${jiro[prop]}`); }
実行結果
hp 162 mp 67 atk 132 def 110
8行目 : prop という変数に、 jiro オブジェクトのプロパティ名を代入され、そのプロパティに対して繰り返されます。
while
while では、条件が true の場合のみ、繰り返しが行われます。
下の例では、 i の値が 5 よりも小さい場合のみ繰り返しが行われます。
script.js
let i = 0; while (i < 5) { console.log(i); i++; }
実行結果
0 1 2 3 4
do while
while と同様に、条件が true の場合のみ、繰り返しが行われます。
while との違いは、必ず1回はループ内のプログラムが実行されるということです。
script.js
let i = 0; do { console.log(i); i++; } while (i < 5);
実行結果
0 1 2 3 4
下の例は、最初から条件が false だった場合です。
script.js
let i = 6; do { console.log(i); i++; } while (i < 5);
実行結果
6
この様に、必ず1回以上、繰り返しが行われます。
break
switch や for , while などで使用されます。
break を使うことで、繰り返しを抜けるなどのことができます。
while を使って、どの様に動くのかを見てみましょう。
script.js
let loop = true; let count = 0; while (loop) { count++; console.log(count); if (count === 5) break; } console.log('繰り返しを抜けました。');
実行結果
1 2 3 4 5 繰り返しを抜けました。
continue
continue は、 for や while などでその繰り返し回数の、始めから再開したい時に使います。
言葉での説明は難しいので、例を見てください。
script.js
let loop = 0; while (loop < 10) { loop++; if (loop > 3 && loop < 8) continue; console.log(loop); }
実行結果
1 2 3 8 9 10
3行目 : 繰り返しを10回行います。
5行目 : loop の値が 3 より大きく、 8 より小さい時、 continue します。
実行結果を見れば、 continue を使った時の数値が抜けていることが分かります。
これは、5行目で繰り返しを再開したため、6行目の console.log(loop); が実行されなかった為です。
配列
一つの変数に、複数の値を代入したい場合、配列を使うと便利です。
実際に使ってみましょう。
script.js
let num = [2,5,4,10]; console.log(num[3]);
実行結果
10
1行目で、 num に複数の数値を代入しています。
この数値は、 num[0] 〜 num[3] の4つに、順番に代入されます。
2行目で、 num[3] に代入されている数値を表示します。
今回では、 0 から数えて 3 つまり、 4番目の値を代入するため、 10 が代入されます。
多次元配列
配列を多次元にすることも可能です。
script.js
let num = [[1,2,3],[4,5,6],[7,8,9]]; console.log(num[0][2]);
実行結果
3
2行目 : num[0][2] で、最初の[]の中の、 0 から数えて 2 、つまり、3番目の数値を表示しているので、 3 と表示されます。
関数
関数とは何度も使用したい、似ている処理をまとめておくものです。
関数には様々な使い方がありますので、いくつか紹介したいと思います。
まずは通常の関数です。
script.js
function sayHello() { console.log('Hello') } sayHello();
実行結果
Hello
無名関数
script.js
let sayHello = function () { console.log('Hello') } sayHello();
実行結果
Hello
即時関数
主に変数名の衝突を避けるのに使用されます。
しかし、変数宣言の let の登場から、即時関数は使われなくなってきております。
ここでは一応、即時関数の使い方も解説しておきたいと思います。
script.js
(function (){ var str = 'Hello'; console.log(str); })(); console.log(str);
もしくは
script.js
(() => { var str = 'Hello'; console.log(str); })(); console.log(str);
実行結果
Hello Uncaught ReferenceError
6行目 : 関数の外側で関数内の変数を呼び出すと、エラーになります。
ブロックスコープが無かった時代は、この様に即時関数を使って、変数の有効範囲を作っておりました。
引数と戻り値
引数や戻り値を使用することで、複雑な関数を作ることができます。
例として、長方形の面積を求める関数を作ってみます。
script.js
let rectangle = function (x, y) { let area = x * y; return area; } let rectangleArea = rectangle(50, 30); console.log(rectangleArea);
実行結果
1500
この例では、横50、縦30の長方形の面積を求めています。
1行目で無名関数を変数 rectangle に代入しています。この時、 ( ) の中に x と y が入っています。
この x と y に、 6行目の、関数の呼び出しで指定した、 50 と 30 が代入されます。これを引数と呼びます。
3行目では、 return を使って、 area 変数に代入した値を返します。この値が、6行目の rectangleArea 変数に代入されます。これが戻り値です。
アロー関数
ECMAScript2015 ( ES6 ) からは、アロー関数が使える様になりました。
先ほどの、長方形の面積を求める関数を、アロー関数に直してみます。
script.js
let rectangle = (x, y) => { let area = x * y; return area; } let rectangleArea = rectangle(50, 30); console.log(rectangleArea);
実行結果
1500
この様に省略して書くことができます。
クラス
ECMAScript2015 ( ES6 ) からは、クラスが使えるようになっております。
言葉では説明が難しいので、例を見ていきましょう。
下の例では、 RPG の敵モンスターをクラスにしてみました。
敵モンスター情報を表示するプログラムです。
script.js
class Monster { constructor(name, atk, def) { this.name = name; this.atk = atk; this.def = def; } info() { console.log(`名前 : ${this.name} 攻撃力 : ${this.atk} 守備力 : ${this.def}`); } } let dragon = new Monster('ドラゴン', 15300, 14200); dragon.info();
実行結果
名前 : ドラゴン 攻撃力 : 15300 守備力 : 14200
1行目で Monster クラスを宣言します。
2行目の constructor には、初期化などのを処理を書きます。
3〜5行目での this は少し厄介なので後で詳しく解説します。とりあえず今は、自分自身 ( Monster ) を示していると思ってください。
7行目では、メソッドを使っています。メソッドは、クラスで使われている関数と思えばいいと思います。
今回では、モンスターの情報を表示するメソッドです。
14行目では、インスタンスを生成しています。
15行目で、 Monster クラスの info() メソッドを呼んでいます。
このように、モンスターに関連したプログラムが、 Monster クラスにまとめられています。これがクラスの使い方です。
しかしこれ、何に役立つのでしょうか?
こんな使い方ができます。
script.js
class Monster { constructor(name, atk, def) { this.name = name; this.atk = atk; this.def = def; } info() { console.log(`名前 : ${this.name} 攻撃力 : ${this.atk} 守備力 : ${this.def}`); } } let slime = new Monster('スライム', 120, 150); let zombie = new Monster('ゾンビ', 300, 230); let dragon = new Monster('ドラゴン', 15300, 14200); slime.info(); zombie.info(); dragon.info();
実行結果
名前 : スライム 攻撃力 : 120 守備力 : 150 名前 : ゾンビ 攻撃力 : 300 守備力 : 230 名前 : ドラゴン 攻撃力 : 15300 守備力 : 14200
14〜16行目で、インスタンスを複数生成することにより、スライム、ゾンビなど、様々なモンスターの情報を表示できるようになりました。
継承
継承を使うことで、親クラスから子クラスへと機能を受け継ぐことができます。
継承には、 extends という命令を使います。
実際に見てみましょう。
script.js
class Ninja { constructor() { this.name = '忍者'; this.skill = '隠れ蓑術'; } useSkill() { console.log(`${this.name}は${this.skill}を使った。`); } } class Kunoichi extends Ninja { useKunoichiSkill() { console.log(`${this.name}はお色気で敵を眩ませた。`); } } let ninja = new Ninja(); let kunoichi = new Kunoichi(); kunoichi.useSkill(); kunoichi.useKunoichiSkill(); ninja.useSkill(); ninja.useKunoichiSkill();
実行結果
忍者は隠れ蓑術を使った。 忍者はお色気で敵を眩ませた。 忍者は隠れ蓑術を使った。 Uncaught TypeError
継承は、11行目で行われています。
RPG などに登場する忍者を例にプログラムを作りました。
まず、忍者のスキルは、隠れ身の術です。
このスキルは、忍者であれば誰でも使うことができます。
また女忍者、いわゆるくノ一は、隠れ蓑術はもちろん、お色気で敵を眩ませることができるとします。
そのような場合に継承が使われます。
1行目で、 Ninja クラスを宣言します。
6行目で、基本スキルのメソッドを作成しています。ここでは、4行目で代入した「隠れ蓑術」を使ったという文字列が表示されるものです。
11行目で、 Ninja クラスを継承した、 Kunoichi クラスを宣言しています。
12行目の、 useKunoichiSkill() メソッドは、くノ一のみが使えるスキルのメソッドです。
17〜18行目で、忍者とくノ一のインスタンスを作成します。
20〜21行目で、くノ一のスキルを発動させています。隠れ蓑術と、お色気の両方のスキルを使えていることが分かります。
23〜24行目で、忍者のスキルを発動させています。スキルは使えますが、くノ一のスキルを使おうとすると、エラーになることが分かります。
is-a
また、継承は is-a の関係に沿って作る様にしましょう。
上の例の場合ですと、くノ一 is a 忍者という関係が成り立ちます。
継承すると便利だからという理由で、継承を適当に多様すると、バグの原因となります。
DOM
DOM を使って、 HTML を操作してみましょう。
DOM とは、 Document Object Model の略で、HTML の要素にアクセスする仕組みです。
では、実際に DOM を使ってみましょう。
文字列の変更
DOM を使って、 HTML の要素にアクセスし、文字列を変更してみましょう。
index.html
<p id="title">どんな盾も貫く矛(ほこ)の紹介</p> <button type="button" onclick="changeText()">タイトルの変更</button>
script.js
let changeText = () => { var node = document.getElementById('title'); node.innerHTML = 'どんな矛(ほこ)も防ぐ盾の紹介'; }
上の例では、 title という id 属性の、文字列を変換しています。
読み込み時は「どんな盾も貫く矛(ほこ)の紹介」とブラウザに表示されますが、ボタンをクリックすることで、「どんな矛(ほこ)も防ぐ盾の紹介」に切り替わります。
script.js 2行目では、 title という id を持つ要素が、 node 変数に代入されます。
script.js 3行目の、 innerHTML を使って、先ほど node 変数に代入した要素の変更をしています。
Strict モード
Strict モードは、 JavaScript の機能を制限するものです。
本来、エラーとならないミスを、エラーとして表示してくれるものです。
script.js
"use strict"; x = 200; console.log(x);
実行結果
Uncaught ReferenceError
この例では、変数宣言が行われていないにもかかわらず、 x 変数をしようしています。
Strict モード でない場合プログラムは動きますが、実際にはあまりよくない書き方です。
Strict モード にすると、この様にエラーを返してくれます。
分割代入
分割代入という代入方法があります。
let [ a, b ] = [ 6, 12 ]; console.log( `aは${a}です` ); console.log( `bは${b}です` );
実行結果
aは6です bは12です
また、これを利用して、変数を入れ替えることも可能です。
let [ a, b ] = [ 6, 12 ]; console.log( `aは${a}です` ); console.log( `bは${b}です` ); [ a, b ] = [ b, a ]; console.log( `aは${a}です` ); console.log( `bは${b}です` );
実行結果
aは6です bは12です aは12です bは6です
map()
map()は配列の要素に対して、様々な操作をすることができるものです。
以下は配列の要素すべてに対し、10をかけるというものです。
let array = [ 0, 1, 2, 3, 4 ]; let map = array.map( (value) => { return value*10; } ); console.log( array ); console.log( map );
実行結果
(5) [0, 1, 2, 3, 4] (5) [0, 10, 20, 30, 40]
さて、以下からはES7以降のバージョンに追加された機能を紹介します。
Array.includes()[ES7]
Array.includes()は、特定の要素が配列に含まれているかどうかを調べます。
script.js
let animals = [ 'cat', 'dog', 'elephant' ]; console.log( animals.includes( 'dog' ) );
実行結果
true
べき乗演算子[ES7]
こちらは演算子のところでも紹介しましたが、べき乗演算子もES7からの機能となります。
それ以前のJavaScriptではMath.pow()というメソッドを使用していました。
script.js
let num = Math.pow( 2, 5 ); console.log( num );
実行結果
32
しかしES7からは**という演算子を使用することで、べき乗の計算ができるようになりました。
let num = 2**5; console.log( num );
実行結果
32
Object.values() [ES8]
Object.values() は、あるオブジェクトのプロパティの値を配列として返します。
今回の例は、RPGの主人公、二郎の強さの数値を配列にしたものです。
script.js
let jiro = { hp: 162, mp: 67, atk: 132, def: 110 } console.log(Object.values(jiro));
実行結果
[162, 67, 132, 110]
Object.entries() [ES8]
Object.entries() は、あるオブジェクトのプロパティを、 key – value の形で配列として返すものです。
script.js
let jiro = { hp: 162, mp: 67, atk: 132, def: 110 } console.log(Object.entries(jiro));
実行結果
[["hp", 162], ["mp", 67], ["atk", 132], ["def", 110]]
String.padStart(), String.padEnd()[ES8]
String.padStart()は文字列を指定した長さに伸ばします。
let str = 'abc'; console.log( str.padStart( 10, 'x' ) );
実行結果
xxxxxxxabc
String.padStart()では、先頭に文字列を加えて伸ばすことができますが、String.padEnd()を使うと最後に文字列を加えて伸ばすことができます。
let str = 'abc'; console.log( str.padEnd( 10, 'x' ) );
実行結果
abcxxxxxxx
try catchの引数を省略[ES10]
以前のJavaScriptでは、try catchの引数を省略することができませんでしたので、必要がない場合でも必ず引数をくっつけていました。
try { console.log( a ); } catch( err ) { console.log( 'エラー' ); }
実行結果
エラー
しかし、ES10からはこの引数を省略できるようになりました。
try { console.log( a ); } catch { console.log( 'エラー' ); }
実行結果
エラー
Object.fromEntries()[ES10]
Object.fromEntries()は、keyとvalueが組み合わさったものをオブジェクトに変換するものです。
const array = [ [ 'a', 100 ], [ 'b', 250 ], [ 'c', 500 ] ]; const object = Object.fromEntries( array ); console.log( object );
実行結果
{a: 100, b: 250, c: 500}
まとめ
JavaScriptは、Webページに動きをつけるのによく使われます。
新しい機能もどんどん増えていきますので、その度に覚える必要がありますが、それによってどんどん便利にもなっていきます。
ただ、新しい機能は、ブラウザが対応していない場合があるので、よく調べて、なにを使うのかを判断する必要があります。
以上、 JavaScript の基本の使い方でした。