基本的なテキストとフォントの装飾 - ウェブ開発を学ぶ

基本的なテキストとフォントの装飾
================

* Overview: Styling text
* 次のページ

この記事では、CSS によるテキストの装飾の習得に向けて旅を始めましょう。 ここでは、フォントの太さ、ファミリーそしてスタイルの設定、フォントの一括指定、テキストの配置とその他のエフェクト、ラインと文字の間隔などを含んだ、テキストやフォントの装飾の基本について詳しく説明します。

| 前提知識: | 基本的なコンピューターリテラシー、HTML の基本（HTML 入門を学ぶ）、CSS の基本（CSS 入門を学ぶ）。 |
| --- | --- |
| 学習目標: | ウェブページのテキストを装飾するために必要な基本的なプロパティとテクニックを学ぶこと。 |

CSS においてテキストの装飾には何が関係していますか？
----------------------------

HTML と CSS を使った作業ですでに経験したように、要素内のテキストは要素のコンテンツボックス内にレイアウトされます。 コンテンツ領域の左上（RTL 言語のコンテンツの場合は右上）から始まり、ラインの終りに向かって流れます。 終りに達すると、次のラインに進み、続けてすべてのコンテンツがボックスに配置されるまで次のラインに進みます。 テキストコンテンツは事実上一連のインライン要素のようにふるまい、互いに隣接するラインに配置され、ラインの終りに達するまで、または、`<br>` 要素を使用して手動で改行を強制しない限り改行を作成しません。

**メモ:** 上の段落で混乱していると感じても問題ありません — 先に進む前に、ボックスモデル理論を磨くために、ボックスモデルの記事に戻って見直してください。

テキストを装飾するために使用される CSS プロパティは、一般的に次の 2 つのカテゴリに分類されます。 この記事では、これらのプロパティを個別に説明します。

* **フォントスタイル**: テキストに適用されるフォントに影響するプロパティで、適用するフォント、大きさ、太字、斜体などに影響します。
* **テキストのレイアウトスタイル**: テキストの間隔やその他のレイアウト機能に影響するプロパティで、例えば、行間や文字間のスペースや、コンテンツボックス内でのテキストの配置方法などを操作できます。

**メモ:** 要素内のテキストはすべて単一の実体として影響を受けることに注意してください。 テキストの一部分を（`<span>` や `<strong>` など）適切な要素でラップしたり、`::first-letter`（要素のテキストの最初の文字を選択）、`::first-line`（要素のテキストの最初の行を選択）、`::selection`（現在カーソルで強調表示されているテキストを選択）のようなテキスト固有の疑似要素を使用しない限り、テキストの一部分を選択して装飾することはできません。

フォント
----

フォントを装飾するためのプロパティを見るためにまっすぐに進みましょう。 この例では、次のような同じ HTML サンプルにいくつかの異なる CSS プロパティを適用します。

```html
<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

完成した例は Github にあります（ソースコードも参照してください）。

### 色

`color` プロパティは、選択された要素の前景のコンテンツの色を設定します（通常はテキストですが、`text-decoration` プロパティを使用してテキストに下線や上線を配置するなど、他のいくつかの要素を含めることもできます）。

`color` は次のように任意の CSS カラー単位を受け入れることができます。

```css
p {
  color: red;
}
```

これにより、次のように段落は標準のブラウザーのデフォルトの黒ではなく赤になります。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

### フォントファミリー

テキストに別のフォントを設定するには、`font-family` プロパティを使用します — これにより、選択した要素に適用するブラウザーのフォント（またはフォントのリスト）を指定できます。 ウェブサイトにアクセスしているマシンで利用可能な場合にのみ、ブラウザーはフォントを適用します。 そうでない場合は、ブラウザーのデフォルトフォントを使用するだけです。 簡単な例はこんな感じです。

```css
p {
  font-family: arial;
}
```

これにより、ページ上のすべての段落に、どのコンピュータでも見られる arial フォントが採用されます。

#### ウェブセーフフォント

フォントの入手可能性と言えば、すべてのシステムで一般的に利用でき、したがってそれほど心配することなく使用できるフォントの数は限られています。これらはいわゆる**ウェブセーフフォント** (web safe fonts) です。

ほとんどの場合、ウェブ開発者は、テキストコンテンツの表示に使用されるフォントをより具体的に制御したいと考えています。 問題は、ウェブページを見るために使用されているコンピュータでどのフォントが利用可能かを知る方法を見つけることです。 あらゆる場合にこれを知る方法はありませんが、ウェブセーフフォントは最も使用されているオペレーティングシステム（Windows、Mac、最も一般的な Linux ディストリビューション、Android、および iOS）のほぼすべての実例で使用可能です。

実際のウェブセーフフォントのリストは、オペレーティングシステムが進化するにつれて変わりますが、少なくとも現時点では次のフォントをウェブセーフと見なすことをお勧めします（それらの多くは 90 年代後半から 2000 年代初頭にかけての Microsoft の Core fonts for the Web の先鞭のおかげで普及しました）。

| 名前 | 総称タイプ | 注 |
| --- | --- | --- |
| Arial | sans-serif | *Arial* に好ましい代替として *Helvetica* を追加するのがベストプラクティスと考えられることがよくあります。 それらのフォントフェイスはほぼ同じですが、*Arial* の方が広く入手可能であっても *Helvetica* はより良い形状をしていると考えられます。 |
| Courier New | monospace | いくつかの OS は *Courier* と呼ばれる *Courier New* フォントの代替（おそらく古い）バージョンを持っています。 *Courier New* と一緒に両方を使用することを推奨します。 |
| Georgia | serif |  |
| Times New Roman | serif | いくつかの OS は *Times* と呼ばれる *Times New Roman* フォントの代替（おそらく古い）バージョンを持っています。 *Times New Roman* と一緒に両方を使用することを推奨します。 |
| Trebuchet MS | sans-serif | このフォントの使用には注意が必要です — モバイル OS では広く使用されていません。 |
| Verdana | sans-serif |  |

**メモ:** さまざまなリソースの中で、cssfontstack.com ウェブサイトには、Windows および macOS オペレーティングシステムで利用可能なウェブセーフフォントのリストがあり、使用しても安全と見なせるものについて判断を下すことができます。

**メモ:** ウェブページとともにカスタムフォントをダウンロードして、フォントの使用方法を自由にカスタマイズできる方法があります。 それは、**ウェブフォント**（web fonts）です。 これはもう少し複雑で、このモジュールの後の別の記事でこれを議論するでしょう。

#### デフォルトフォント

CSS はフォントの 5 つの総称名を定義しています: セリフ（`serif`）、サンセリフ（`sans-serif`）、等幅（`monospace`）、筆記体（`cursive`）、ファンタジー（`fantasy`）。 これらは非常に一般的なものであり、それらの総称名を使用するときに使用される正確なフォントは各ブラウザー次第であり、それらが実行されているオペレーティングシステムごとに異なります。 これは、ブラウザーが最低限適切なフォントを提供するように最善を尽くそうとする場合の*最悪のシナリオ*を表します。 `serif`、`sans-serif`、および `monospace` はかなり予測可能であり、妥当なものを提供するはずです。 その一方で、`cursive` や `fantasy` はそれほど予測できないので、慎重に使用してテストすることをお勧めします。

5 つの名前は次のように定義されています。

| 用語 | 定義 | 例 |
| --- | --- | --- |
| `serif` | セリフ（いくつかの書体のストロークの終わりに見られる隆起やその他の細部）を持つフォントです。 | My big red elephant |
| `sans-serif` | セリフがないフォントです。 | My big red elephant |
| `monospace` | すべての文字が同じ幅を持つフォントで、通常はコードリストで使用されます。 | My big red elephant |
| `cursive` | 流れるような連続したストロークで、手書き文字を模倣することを目的としたフォントです。 | My big red elephant |
| `fantasy` | 装飾的なフォントです。 | My big red elephant |

#### フォントスタック

ウェブページで使用したいフォントの可用性を保証することはできないため（ウェブフォントでさえ何らかの理由で失敗する*可能性*もあります）、ブラウザーに複数のフォントから選択できるように**フォントスタック**（font stack）を指定できます。 これは単に、次のようにカンマで区切られた複数のフォント名からなる `font-family` の値です。

```css
p {
  font-family: "Trebuchet MS", Verdana, sans-serif;
}
```

そのような場合、ブラウザーはリストの先頭から始めて、そのフォントがマシンで利用可能かどうかを確認します。 そうであれば、そのフォントを選択した要素に適用します。 そうでない場合は、次のフォントに移動します。

リストされているフォントがどれも利用できない場合、ブラウザーが少なくともほぼ適切なものを提供できるように、スタックの最後に適切な総称フォント名を指定することをお勧めします。 この点を強調するために、他のオプションが利用できない場合、段落にはブラウザーのデフォルトの serif フォントを使用します — これは通常は Times New Roman です — これは sans-serif フォントには不適切です！

**メモ:** `Trebuchet MS` のように、複数の単語を含むフォント名は `"Trebuchet MS"` のように引用符で囲む必要があります。

#### font-family の例

前の例に追加して、次のように段落に sans-serif フォントを付けます。

```css
p {
  color: red;
  font-family: Helvetica, Arial, sans-serif;
}
```

これにより、次のような結果が得られます。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

### フォントサイズ

前のモジュールの CSS の値と単位の記事で、長さとサイズの単位を確認しました。 フォントサイズ（`font-size` プロパティで設定）は、これらの単位のほとんど（およびパーセントなどの他の単位）で測定された値を取ることができますが、テキストのサイズを設定するために使用する最も一般的な単位は次のとおりです。

* `px` (pixels): テキストを表示したい高さのピクセル数。 これは絶対的な単位です — それはほとんどどんな状況でもページ上のフォントの同じ最終的な計算値になります。
* `em`: `1em` は、現在装飾している要素の親要素に設定されているフォントサイズ（より具体的には、親要素の内側に含まれる大文字の M の幅）に等しくなります。 フォントサイズの異なるネストされた要素が多数設定されている場合には厄介な作業になるかもしれませんが、以下に示すように、それは実行可能です。 なぜわざわざそうする？ 慣れると非常に自然になり、テキストだけでなく、`em` を使用してすべてのサイズを変更できます。 ウェブサイト全体を `em` を使用してサイズ設定することができ、これにより、メンテナンスが簡単になります。
* `rem`: これらは `em` とまったく同じように機能しますが、`1rem` が親要素ではなく文書のルート要素に設定されたフォントサイズ（つまり `<html>`）に等しい点が異なります。 これにより、フォントサイズを簡単に計算することができますが、残念ながら Internet Explorer 8 以下では `rem` はサポートされていません。 プロジェクトで古いブラウザーをサポートする必要がある場合は、`em` や `px` を使用するか、REM-unit-polyfill などのポリフィルを使用することができます。

要素の `font-size` は、その要素の親要素から継承されます。 これはすべてドキュメント全体のルート要素 — `<html>` — で始まり、`font-size` はブラウザー間で標準で `16px` に設定されています。 ルート要素内の段落（またはブラウザーによって設定された異なるサイズを持たない他の要素）は、最終サイズが `16px` になります。 他の要素はデフォルトサイズが異なる場合があります。 例えば、`<h1>` 要素のサイズはデフォルトで `2em` に設定されているため、最終的なサイズは `32px` になります。

入れ子になった要素のフォントサイズを変更し始めると、物事はより複雑になります。 例えば、ページに `<article>` 要素があり、その `font-size` を `1.5em`（これは計算すると `24px` の最終的なサイズになります）に設定し、次に `<article>` 要素内の段落に `20px` で計算したフォントサイズを使用するようにしたい場合に、あなたは何 `em` の値を使用しますか？

```html
<!-- ドキュメントのベースフォントサイズは 16px です -->
<article>
  <!-- ここのフォントサイズが 1.5em の場合 -->
  <p>My paragraph</p>
  <!-- 20px のフォントサイズにするにはどう計算しますか？ -->
</article>
```

その `em` 値を 20 / 24 、つまり `0.83333333em` に設定する必要があります。 数学は複雑になる可能性があるため、装飾方法には注意が必要です。 可能な限り `rem` を使用して、物事を単純にし、可能な限りコンテナ要素のフォントサイズを設定しないようにするのが最善です。

#### 簡単なサイズ設定の例

テキストのサイズを変更するときは、通常、ドキュメントのベース `font-size` を `10px` に設定することをお勧めします。 そうすれば、数学の計算がはるかに簡単になります — その場合、必要な `(r)em` 値は、16 ではなく、10 で割ったピクセルフォントサイズです。 これで、ドキュメント内のさまざまな種類のテキストのサイズを簡単に変更できます。 スタイルシートの指定された領域にすべての `font-size` の規則セットをリストすることをお勧めします。 そうすれば、それらは簡単に見つけられます。

新しい結果はこんな感じです。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```css
html {
  font-size: 10px;
}

h1 {
  font-size: 2.6rem;
}

p {
  font-size: 1.4rem;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
}
```

### フォントスタイル、フォントの太さ、テキスト変換、テキスト飾り

CSS は、テキストの視覚的な太さや強調を変更するために次の 4 つの共通のプロパティを提供します。

* `font-style`: イタリック体テキストのオンとオフを切り替えるために使用されます。 可能な値は次のとおりです（何らかの理由でイタリック装飾をオフにしたい場合を除いて、これを使用することはめったにありません）。
    + `normal`: テキストを通常のフォントに設定します（既存のイタリック体をオフにします）。
    + `italic`: 利用できる場合は、*イタリック体版のフォント*を使用するようにテキストを設定します。 利用できない場合は、代わりに `oblique` でイタリック体をシミュレートします。
    + `oblique`: 通常版を斜めにして作成された、イタリック体フォントのシミュレート版を使用するようにテキストを設定します。
* `font-weight`: テキストの太さを設定します。 利用可能なフォントのバリエーションが多数ある場合（*-light*、*-normal*、*-bold*、*-extrabold*、*-black* など）、これには多くの値がありますが、現実的には `normal` と `bold` 以外のものを使用することはほとんどありません。
    + `normal`, `bold`: 標準および**太字**のフォントの太さ。
    + `lighter`, `bolder`: 現在の要素の太さを、親要素の太さよりも 1 段階細くまたは太くします。
    + `100`～`900`: 必要に応じて、上記のキーワードよりもきめ細かい制御を提供する太さの数値。
* `text-transform`: フォントを変換するように設定できます。 値は次のとおりです。
    + `none`: 変換を禁止します。
    + `uppercase`: すべてのテキストを大文字（all text to capitals）に変換します。
    + `lowercase`: すべてのテキストを小文字（ALL TEXT TO LOWER CASE）に変換します。
    + `capitalize`: すべての単語を最初の文字を大文字にする（have the first letter capitalized）ように変換します。
    + `full-width`: 例えば、ラテン文字を（中国語、日本語、韓国語など）アジア言語のグリフと一緒に揃えて、等幅フォントのように、固定幅の四角形の中にすべてのグリフを書く（written inside a fixed-width square）ように変換します。
* `text-decoration`: フォントのテキスト飾りを設定/設定解除します（主にリンクのデフォルトの下線を解除するために使用します）。 使用可能な値は次のとおりです。
    + `none`: 既に存在するテキスト飾りをすべて解除します。
    + `underline`: **テキストに下線を引きます**。
    + `overline`: テキストに上線を付けます。
    + `line-through`: ~~テキストの上に取り消し線を引きます~~。複数の飾りを同時に追加したい場合は、`text-decoration: underline overline` のように、`text-decoration` は一度に複数の値を受け入れることができます。 また、`text-decoration` は、`text-decoration-line`、`text-decoration-style`、および `text-decoration-color` の一括指定プロパティです。 例えば、`text-decoration: line-through red wavy` のように、これらのプロパティ値の組み合わせを使用して、興味深い効果を生み出すことができます。

例にこれらのプロパティをいくつか追加してみましょう。

新しい結果はこんな感じです。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```css
html {
  font-size: 10px;
}

h1 {
  font-size: 2.6rem;
  text-transform: capitalize;
}

h1 + p {
  font-weight: bold;
}

p {
  font-size: 1.4rem;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
}
```

### テキストのドロップシャドウ

`text-shadow` プロパティを使ってテキストにドロップシャドウを付けることができます。 次の例に示すように、これは最大 4 つの値を取ります。

```css
text-shadow: 4px 4px 5px red;
```

4 つのプロパティは次のとおりです。

1. 元のテキストからの影の水平方向のオフセット — これは、ほとんどの CSS の長さとサイズの単位を取ることができますが、最も一般的には `px` を使用します。 この値を含める必要があります。
2. 元のテキストからの影の垂直方向のオフセット — 基本的に水平方向のオフセットと同じようにふるまいますが、影を左右に移動するのではなく上下に移動する点が異なります。 この値を含める必要があります。
3. ぼかし半径 — 値が大きいほど、影はより広く分散されます。 この値が含まれていない場合、デフォルトは 0 になり、ぼかしは行われません。 これは、ほとんどの CSS の長さとサイズの単位を取ることができます。
4. 影のベースカラー — 任意の CSS カラー単位を取ります。 含まれていない場合、デフォルトは `black` です。

**メモ:** 正のオフセット値は影を右下に移動させますが、`-1px -1px` のように負のオフセット値を使用して影を左上に移動させることもできます。

#### 複数の影

複数の影の値をコンマで区切って含めることで、次のように同じテキストに複数の影を付けることができます。

```css
text-shadow:
  -1px -1px 1px #aaa,
  0px 4px 1px rgba(0, 0, 0, 0.5),
  4px 4px 5px rgba(0, 0, 0, 0.7),
  0px 0px 7px rgba(0, 0, 0, 0.4);
```

これを Tommy the cat の例の `<h1>` 要素に適用すると、結果は次のようになります。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```
html {
  font-size: 10px;
}

h1 {
  font-size: 26px;
  text-transform: capitalize;
  text-shadow:
    -1px -1px 1px #aaa,
    0px 2px 1px rgba(0, 0, 0, 0.5),
    2px 2px 2px rgba(0, 0, 0, 0.7),
    0px 0px 3px rgba(0, 0, 0, 0.4);
}

h1 + p {
  font-weight: bold;
}

p {
  font-size: 14px;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
}
```

**メモ:** Sitepoint の記事 Moonlighting with CSS text-shadow で、`text-shadow` の使い方のより興味深い例を見ることができます。

テキストのレイアウト
----------

基本的なフォントのプロパティ以外の方法で、テキストのレイアウトに影響を与えるために使用できるプロパティを見てみましょう。

### テキストの配置

`text-align` プロパティは、テキストを含むコンテンツボックス内でのテキストの配置方法を制御するために使用されます。 利用可能な値は次の通りで、通常のワードプロセッサアプリケーションとほとんど同じように機能します。

* `left`: テキストを左揃えにします。
* `right`: テキストを右揃えにします。
* `center`: テキストを中央揃えにします。
* `justify`: テキストを両端揃えにします。 すべてのテキストのラインが同じ幅になるように、単語の間隔を変えてテキストを広げます。 これは慎重に使用する必要があります — 特に、長い単語が多数含まれている段落に適用すると、ひどく見えます。 もしこれを使うつもりなら、`hyphens` のような他の何かを使用して、複数ラインにまたがる長い単語を分割することも考えてください。

例の `<h1>` に、`text-align: center;` を適用した場合、次のようになるでしょう。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```
html {
  font-size: 10px;
}

h1 {
  font-size: 2.6rem;
  text-transform: capitalize;
  text-shadow:
    -1px -1px 1px #aaa,
    0px 2px 1px rgba(0, 0, 0, 0.5),
    2px 2px 2px rgba(0, 0, 0, 0.7),
    0px 0px 3px rgba(0, 0, 0, 0.4);
  text-align: center;
}

h1 + p {
  font-weight: bold;
}

p {
  font-size: 1.4rem;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
}
```

### ラインの高さ

`line-height` プロパティはテキストの各ラインの高さを設定します — これはほとんどの長さとサイズの単位をとることができますが、乗数として機能し、一般的に最良の選択肢と考えられる単位なしの値をとることもできます — `line-height` を得るために `font-size` が乗算されます。 本文はラインが離れていると、一般的に見栄えがよく、読みやすくなります。 推奨されるラインの高さは約 1.5 〜 2（ダブルスペース）です。 したがって、テキストのラインをフォントの高さの 1.5 倍に設定するには、次のようにします。

```css
line-height: 1.5;
```

この例の `<p>` 要素にこれを適用すると、次のようになります。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```
html {
  font-size: 10px;
}

h1 {
  font-size: 2.6rem;
  text-transform: capitalize;
  text-shadow:
    -1px -1px 1px #aaa,
    0px 2px 1px rgba(0, 0, 0, 0.5),
    2px 2px 2px rgba(0, 0, 0, 0.7),
    0px 0px 3px rgba(0, 0, 0, 0.4);
  text-align: center;
}

h1 + p {
  font-weight: bold;
}

p {
  font-size: 1.4rem;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
  line-height: 1.5;
}
```

### 文字と単語の間隔設定

`letter-spacing` プロパティと `word-spacing` プロパティを使用すると、テキスト内の文字と単語の間隔を設定できます。 これらはあまり使用しませんが、ある外観を得るためや、特に濃いフォントの読みやすさを向上させるために使用することがあります。 それらはほとんどの長さとサイズの単位を取ることができます。

例として、この例の `<p>` 要素の最初のラインに次を適用したとします。

```css
p::first-line {
  letter-spacing: 2px;
  word-spacing: 4px;
}
```

次のようになります。
```

<h1>Tommy the cat</h1>

<p>I remember as if it were a meal ago...</p>

<p>
  Said Tommy the Cat as he reeled back to clear whatever foreign matter may have
  nestled its way into his mighty throat. Many a fat alley rat had met its
  demise while staring point blank down the cavernous barrel of this awesome
  prowling machine. Truly a wonder of nature this urban predator — Tommy the cat
  had many a story to tell. But it was a rare occasion such as this that he did.
</p>
```

```
html {
  font-size: 10px;
}

h1 {
  font-size: 2.6rem;
  text-transform: capitalize;
  text-shadow:
    -1px -1px 1px #aaa,
    0px 2px 1px rgba(0, 0, 0, 0.5),
    2px 2px 2px rgba(0, 0, 0, 0.7),
    0px 0px 3px rgba(0, 0, 0, 0.4);
  text-align: center;
}

h1 + p {
  font-weight: bold;
}

p::first-line {
  letter-spacing: 2px;
  word-spacing: 4px;
}

p {
  font-size: 1.4rem;
  color: red;
  font-family: Helvetica, Arial, sans-serif;
  line-height: 1.5;
}
```

### その他の検討に値するプロパティ

上記のプロパティは、ウェブページ上でテキストを装飾する方法のアイデアを与えますが、使うことができるもっと多くのプロパティがあります。 ここでは最も重要なものだけを取り上げたいと思います。 上記の使い方に慣れてきたら、次のことも調べてください。

フォントスタイル

* `font-variant`: スモールキャップと通常の代替フォントを切り替えます。
* `font-kerning`: フォントのカーニングオプションのオンとオフを切り替えます。
* `font-feature-settings`: さまざまな OpenType フォント機能のオンとオフを切り替えます。
* `font-variant-alternates`: 与えられたフォントフェイスのための代替グリフの使用を制御します。
* `font-variant-caps`: 代替大文字グリフの使用を制御します。
* `font-variant-east-asian`: 日本語や中国語など、東アジアの文字の代替グリフの使用方法を制御します。
* `font-variant-ligatures`:テキストで使用される合字と文脈形式を制御します。
* `font-variant-numeric`: 数字、分数、および序数記号の代替グリフの使用方法を制御します。
* `font-variant-position`: 上付き文字または下付き文字として配置された、小さいサイズの代替グリフの使用方法を制御します。
* `font-size-adjust`: 実際のフォントサイズとは無関係にフォントの表示サイズを調整します。
* `font-stretch`: 与えられたフォントの可能な代替の伸縮バージョン間で切り替えます。
* `text-underline-position`: `text-decoration-line` プロパティの `underline` 値を使用して設定された下線の位置を指定します。
* `text-rendering`: テキストレンダリングの最適化を試します。

テキストのレイアウトスタイル

* `text-indent`: テキスト内容の最初のラインの始まりの前にどれだけの水平スペースを残すべきかを指定します。
* `text-overflow`: 表示されないオーバーフローしたコンテンツがユーザーに通知される方法を定義します。
* `white-space`: 要素内の空白とそれに関連する改行の扱い方を定義します。
* `word-break`: 単語内で改行するかどうかを指定します。
* `direction`: テキストの方向を定義します（これは言語に依存します。 通常、テキストの内容に結び付けられているので、HTML にその部分を処理させる方が良いです）。
* `hyphens`: サポートしている言語のハイフネーションをオンまたはオフにします。
* `line-break`: アジア言語の改行を緩和または強化します。
* `text-align-last`: ブロックの最後のラインまたは強制改行の直前のラインの配置方法を定義します。
* `text-orientation`: ライン内での文字の向きを定義します。
* `overflow-wrap`: オーバーフローを防ぐために、ブラウザーが単語内で改行できるかどうかを指定します。
* `writing-mode`: テキストのラインを水平に配置するか垂直に配置するか、およびそれに続いてラインが流れる方向を定義します。
フォントの一括指定
---------

多くのフォントプロパティは、一括指定プロパティの `font` を介して設定することもできます。 これらは、`font-style`、`font-variant`、`font-weight`、`font-stretch`、`font-size`、`line-height`、`font-family` の順に書きます。

これらすべてのプロパティのうち、`font` 一括指定プロパティを使用する場合に必要なのは、`font-size` と `font-family` のみです。

`font-size` プロパティと `line-height` プロパティの間にスラッシュを入れる必要があります。

完全な例は次のようになります。

```css
font:
  italic normal bold normal 3em/1.5 Helvetica,
  Arial,
  sans-serif;
```

能動的学習: テキストの装飾で遊ぶ
-----------------

この能動的学習セッションでは、具体的な演習はありません。 フォントやテキストのレイアウトのプロパティをいくつか試してみて、作成できるものを確認してください！ オフラインの HTML / CSS ファイルを使用してこれを行うか、下記のライブ編集可能な例にコードを入力することができます。

間違えた場合は、*Reset* ボタンを使用していつでもリセットできます。
```

<div
 class="body-wrapper"
 style="font-family: 'Open Sans Light',Helvetica,Arial,sans-serif;">
  <h2>HTML Input</h2>
  <textarea
 id="code"
 class="html-input"
 style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;">
  <p>Some sample text for your delight</p></textarea
 >

  <h2>CSS Input</h2>
  <textarea
 id="code"
 class="css-input"
 style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;">
p {

  }</textarea
 >

  <h2>Output</h2>
  <div
 class="output"
 style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"></div>
  <div class="controls">
    <input
 id="reset"
 type="button"
 value="Reset"
 style="margin: 10px 10px 0 0;" />
  </div>
</div>
```

```
var htmlInput = document.querySelector(".html-input");
var cssInput = document.querySelector(".css-input");
var reset = document.getElementById("reset");
var htmlCode = htmlInput.value;
var cssCode = cssInput.value;
var output = document.querySelector(".output");

var styleElem = document.createElement("style");
var headElem = document.querySelector("head");
headElem.appendChild(styleElem);

function drawOutput() {
  output.innerHTML = htmlInput.value;
  styleElem.textContent = cssInput.value;
}

reset.addEventListener("click", function () {
  htmlInput.value = htmlCode;
  cssInput.value = cssCode;
  drawOutput();
});

htmlInput.addEventListener("input", drawOutput);
cssInput.addEventListener("input", drawOutput);
window.addEventListener("load", drawOutput);
```

まとめ
---

この記事のテキストで遊んで楽しんでくださいね！ 次の記事では、HTML リストの装飾について知っておくべきことをすべて説明します。

* Overview: Styling text
* 次のページ


JavaScript の第一歩 - ウェブ開発を学ぶ

JavaScript の第一歩
===============

最初の JavaScript のモジュールでは、初めて JavaScript を書く実践的な経験を体験する前に、「JavaScript とは何？」や「どのようなもの？」や「何ができる？」といったような基本的な質問に答えます。その後、変数や文字列、 数値、配列といったような言語の内容をお話しします。

#### フロントエンドのウェブ開発者になりたいですか？

目標に向かって取り組むために必要なすべての重要な情報を含むコースをまとめました。

**始めましょう**

前提条件
----

このモジュールを始めるには JavaScript の知識は必要ありませんが、HTML や CSS に少し慣れている必要があります。JavaScript の学習を開始する前に以下のモジュールを学習することをお勧めします。

* ウェブ入門 (JavaScript の基本 を含む)
* HTML 入門
* CSS の第一歩

**メモ:** 作業しているコンピューターやタブレットなどの端末で、自分でファイルを作れない場合は、 JSBin や Glitch といったようなオンラインコーディングプログラムで（ほとんどの場合）試すことができます。

ガイド
---

JavaScript とは

MDN の初心者向け JavaScript コースへようこそ！この最初の記事では JavaScript を高い視点から見ていき、「それは何ですか？」「それで何ができますか？」などの質問に答え、 JavaScript の目的があなたに受け入れられるものであるかを確認します。

最初のダイブ

JavaScript の理論についていくつか学びましたが、それで何ができるのでしょう？完全に実践的なチュートリアルを通して、JavaScript の基本機能の短期集中コースを提供します。 ここでは、簡単な数字当てゲームを段階的に作っていきます。

何が間違っている？ JavaScript のトラブルシューティング

前の記事で数字当てゲームを構築した時に、うまく動かなかったかもしれません。心配しないでください —この記事は、JavaScript のプログラムにエラーを見つけて修正するシンプルな方法を提供することで、こうした大変な事態からあなたを手助けすることを目的としています。

必要な情報を保存する — 変数

前の 2 つの記事を読んで、JavaScript が何であるか、あなたのために何ができるか、他のウェブテクノロジーと一緒に使う方法、そして高い視点から見た主な機能を知ったことでしょう。この記事では実際の基礎に着目し、JavaScript の最も基本的な構成要素を扱う方法を見ていきます ― それが変数です。

JavaScript での基本演算 — 数値と演算子

ここで、JavaScript における数学について論じます。指示に従ってうまく数値を操作するために、演算子やその他の機能を組み合わる方法を説明します。

テキストを扱う — JavaScript での文字列

次に、文字列に注目します ― プログラミングではテキストのことをこう呼びます。この記事では、文字列の作成、文字列の引用符のエスケープ、およびそれらの結合など、JavaScript を学習するにあたって本当に知っておくべき、文字列についてのすべての一般的な事柄を見ていきます。

便利な文字列メソッド

文字列の基本について見てきましたが、文字列の長さの取得、文字列の結合と分割、文字列内の文字の置換、その他の文字列の置換など、組込みメソッドを使用して文字列に対して実行できる便利な操作について考えてみましょう。

配列

このモジュールの最後の記事では、配列を見ていきます — 単一の変数名の下に複数のデータ項目のリストを保存するのに適した方法です。ここでは、なぜこれが便利なのかを確認してから、配列の作成方法、配列に格納された項目の取り出し、追加、削除などの方法を学びます。

課題
--

以下の成績評価では、上のガイドで取り上げた JavaScript の基礎についての理解をテストします。

バカ話ジェネレーター

この課題では、このモジュールの記事で取り上げた知識の一部を用いて、ランダムなバカ話を生成する愉快なアプリの作成に適用することを求められます。楽しんで取り組みましょう！

関連情報
----

Learn JavaScript

 短いレッスンとインタラクティブなテストを使用して、自動化された評価に基づいた、インタラクティブな環境で JavaScript を学びます。
 最初の 40 レッスンは無料で、コース全体を少額の 1 回払いで利用できます。


クライアントサイド Web API - ウェブ開発を学ぶ

クライアントサイド Web API
=================

ウェブサイトやアプリケーション用にクライアント側の JavaScript を書いていると、すぐに**アプリケーションプログラミングインターフェース** (**A**pplication **P**rogramming **I**nterfaces、**API**) にでくわします。API とはブラウザーやサイトが動作している OS の様々な面を操作したり、他のウェブサイト、サービスから取得したデータを操作するためのプログラムされた機能です。このモジュールでは API とは何か、開発作業の中でよく見かける最もよく利用される API のいくつかについて、どのように使うかを説明していきます。

#### フロントエンドのウェブ開発者を目指している方へ

ゴールに向かって頑張るために必要な情報をまとめたコースをご用意しました。

**始めましょう**

前提条件
----

このモジュールをよく理解するためには、ここまでの一連の JavaScript に関するモジュール（第一歩、構成要素 と JavaScript オブジェクト）の学習をすませているべきです。これらのモジュールでは大抵簡単な API を使っていますが、その助けなしにクライアント側の JavaScript を書き上げるのは難しいからです。このチュートリアルの中では、JavaScript 言語のコア部分については十分理解しているものとして、よく使われる Web API についてもう少し詳しく探っていきます。

HTML と CSS に関する基礎知識も役に立つでしょう。

**メモ:** もし自分のファイルを作成できないような端末上で作業しているなら、大半のコード例を JSBin や Glitch のようなオンラインプログラム作成・実行環境で試してみることもできます。

ガイド
---

Web API の紹介

まずは API を高い視点から見ていきます — これは何なのか、どう働くのか、あなたのコードでどう使うのか、どういう風に作られているのか? また様々なクラスの API が何なのか、どんな使い方があるのかも見ていきます。

文書の操作

ウェブページやアプリケーションを書くとき、最も一般的なことのひとつは、何らかの方法でウェブ文書を操作することでしょう。これは通常、ドキュメントオブジェクトモデル (DOM) を使用することで行われます。これは HTML とスタイル設定情報をコントロールするための API のセットで、 `Document` オブジェクトを多用します。この記事では、 DOM を使用する方法を詳しく見ていきます。また、他にも興味深い方法であなたの環境を変化させることができる API もいくつか紹介します。

サーバーからのデータ取得

また、現代のウェブサイトやアプリケーションでは、新しいページ全体を読み込むことなくウェブページの節を更新するために、サーバーから個々のデータ項目を取得することも非常に一般的なタスクです。この一見小さなことが、サイトのパフォーマンスや動作に大きな影響を及ぼしています。この記事では、この概念を説明し、 `XMLHttpRequest` や Fetch API など、これを可能にする技術について見ていきます。

サードパーティの API

これまで取り上げた API はブラウザーに内蔵されていますが、すべての API が内蔵されているわけではありません。 Google マップ、Twitter、Facebook、PayPal など、多くの大規模なウェブサイトやサービスが API を提供しており、開発者はそれらのデータ（例：ブログに Twitter のストリームを表示する）やサービス（例：サイトにカスタム Google マップを表示したり、 Facebook ログインを使ってユーザーにログインしてもらう）を使用することができます。この記事では、ブラウザー API とサードパーティ API の違いを見て、後者の典型的な使用方法をいくつか示します。

グラフィックの描画

ブラウザーにはグラフィックを描くためのとても強力なツールがいくつか組み込まれています。SVG (Scalable Vector Graphics) 言語から、 HTML の `<canvas>` キャンバス要素に描画するための API （キャンバス API や WebGLを参照）まで。 この記事ではキャンバス API への導入を説明し、もっと深く学習していくためのリソースをご紹介します。

動画と音声の API

HTML には文書にリッチなメディアを埋め込むための要素 — `<video>` と `<audio>` — が備わっています。それぞれに再生やシークなどの操作するための独自 API を備えています。この記事では独自の再生操作パネルを作成するような、よくある仕事をどうやればいいのかお見せします。

クライアント側ストレージ

現代のブラウザーには、ウェブサイトに関するデータを保存し必要なときに取り出すための様々に異なる技術が実装されており、これを使ってデータを長期間保存したり、サイトをオフラインに保存したりなどなどができます。この記事ではこれらがいかに動作するのか、その基本の基本について説明します。


JavaScript の構成要素 - ウェブ開発を学ぶ

JavaScript の構成要素
================

このモジュールでは、条件付きステートメント、ループ、関数、イベントなど一般的に発生するコードブロックの種類に注目し、JavaScript の重要な基本機能をすべてカバーしていきます。コースの中で既にこれらを目にしているのですが、説明を省いてきました。ここではすべて明示的に説明を行います。

#### フロントエンドのウェブ開発者を目指している方へ

ゴールに向かって頑張るために必要な情報をまとめたコースをご用意しました。

**始めましょう**

前提条件
----

このモジュールを始める前に、HTML や CSS の基本に慣れておくべきです。また前のモジュールの JavaScript の第一歩 も終了させておくべきです。

**メモ:** もしあなたが作業しているコンピューターやタブレット、その他の端末で自分でファイルを作れない場合は、JSBin や Glitch といったようなオンラインコーディングプログラムで（ほとんどの場合）試すことができます。

ガイド
---

コード内で決定を下す — 条件

どんなプログラミング言語でも、コードは異なる入力に応じて決定を下し、それに応じてアクションを実行する必要があります。例えば、ゲームではもしプレイヤーのライフが 0 だった場合、ゲームオーバーになります。お天気アプリでは、朝に見た場合には朝日の画像を表示し、夜に見た場合には星と月を表示します。この記事では、条件の構造が JavaScript でどのように機能するかを説明します。

ループコード

場合によっては、一度にタスクを複数回実行しなければならないことがあります。 例えば名前のリスト全体を調べる場合です。プログラミング時に、ループはこのような処理を非常にうまく実行します。ここでは JavaScript のループ構造を見ていきます。

関数 — 再利用可なコードブロック

コーディングのもう一つの重要な概念は**関数**です。 **関数**を使用すると、定義されたブロック内に単一のタスクを実行するコードを格納し、同じコードを複数回入力するのではなく、単一の短いコマンドを使用して必要となる時にコードを呼び出すことができます。この記事では、基本的な構文、関数、スコープ、引数を呼び出す方法と定義する方法など、関数の背後にある基本的な概念について説明します。

独自の関数を構築する

前の記事で扱った必須の理論の多くを用いて、この記事では実用的な体験を提供しています。ここでは、独自のカスタム関数を構築するための練習をします。 また進むにつれ、関数を扱うためのさらに便利な詳細についても説明します。

関数の返値

関数について知っておくべき必須の概念の最後は返値です。関数によっては完了後に意味のある値を返しませんが、それ以外の関数は返します。値が何であるか、コードでそれらを使用する方法、独自のカスタム関数で有用な値を返す方法を理解することが重要です。

イベントへの入門

イベントとは、プログラミング中のシステムで発生するアクションまたは事象のことで、システムによって通知され、必要に応じて何らかの方法で応答できるようにするものです。例えば、ユーザーがウェブページ上のボタンをクリックすると、情報ボックスを表示することでそのアクションに応答することができます。この最後の記事では、イベントを取り巻くいくつかの重要な概念について説明し、それらがブラウザーでどのように機能するかを見ていきます。

評価
--

以下の評価は、上のガイドで取り上げた JavaScript の基礎についての理解をテストします。

イメージギャラリー

JavaScript の基本的な構成要素を見てきましたので、JavaScript で動く画像ギャラリーという、多くのウェブサイトで見ることができるかなり一般的なアイテムを構築することで、ループ、関数、条件文、イベントに関する知識をテストします。

関連情報
----

Learn JavaScript

ウェブ開発者を目指す人のための優れたリソース - 短いレッスンとインタラクティブなテスト、自動評価によるガイドで、インタラクティブな環境で JavaScript を学ぶことができます。最初の 40 レッスンは無料で、少額の一回払いでこのコースのすべてを利用することができます。


JavaScriptのコードのよくある問題を解決する - ウェブ開発を学ぶ

JavaScriptのコードのよくある問題を解決する
==========================

JavaScript のコードが正しく動作しないので修正したい、というような場合にみられる、よくある問題の解決方法へのリンクを以下に示します。

初学者がよく陥る誤り
----------

### スペル、大文字小文字を訂正する

コードが正しく動かない場合や、何かが未定義であるとブラウザーがエラーを出した場合、変数名や関数名のスペルが正しいか確認してください。

ブラウザーの組み込み関数についての正誤例:

| 正 | 誤 |
| --- | --- |
| `getElementsByTagName()` | `getElementbyTagName()` |
| `getElementsByName()` | `getElementByName()` |
| `getElementsByClassName()` | `getElementByClassName()` |
| `getElementById()` | `getElementsById()` |

### セミコロンの位置

セミコロンの位置に誤りがないか確認してください。

例:

| 正 | 誤 |
| --- | --- |
| `elem.style.color = 'red';` | `elem.style.color = 'red;'` |

### 関数

関数についての誤りは何点かあります。

よくある誤りの一つとして、関数を定義したがどこからも呼び出していない、というものがあります。

例:

```js
function myFunction() {
  alert("This is my function.");
}
```

上記のコードで定義した関数は、例えば以下のように呼び出さないかぎり何もしません。

```js
myFunction();
```

#### 関数のスコープ

関数は関数自身のスコープを持ちます。変数をグローバルに（関数の外で）定義するか、戻り値として変数の値を関数の外に返さないかぎり、関数の外から関数の中で定義された変数にアクセスすることはできません。

#### return 文の後ろのコードの実行

return 文で関数から値を返したとき、JavaScript のインタプリタはその関数を終了します。return 文の後ろのコードは実行されません。

Firefox などのいくつかのブラウザーは、return 文の後ろにコードが存在する場合、開発者ツールのコンソールにエラーメッセージを出力します。Firefox が出力するメッセージは "unreachable code after return statement" です。

### オブジェクトリテラル記法 vs 代入

通常、JavaScript で代入する場合、等号を使います。

例:

```js
var myNumber = 0;
```

オブジェクトの場合は、メンバー名とその値をコロンで区切り、メンバー間をカンマで区切る必要があります。

例:

```js
var myObject = {
  name: "Chris",
  age: 38,
};
```

基本的な定義
------

* JavaScript とは
* 変数とは
* 文字列とは
* 配列とは
* ループとは

* 関数とは
* イベントとは
* オブジェクトとは
* JSON とは
* Web API とは
* DOM とは
初級のユースケース
---------

### 全般

* JavaScript をページに追加するには
* JavaScript のコードにコメントを追加するには
### 変数

* 変数を宣言するには
* 変数を値で初期化するには
* 変数の値を変更するには(代入演算子についても参照してください)
* JavaScript のデータ型とは
* 「弱い型付け」とは
### 数学

* Web 開発で扱わなければならない数値型とは
* JavaScript での基本的な算術演算の方法とは
* JavaScript での演算子の優先順位とは
* JavaScript で値をインクリメント、デクリメントするには
* JavaScript で値を比較するには(どちらが大きいか、ある値が別の値と等しいか、など)
### 文字列

* JavaScript で文字列を作成するには
* シングルクォーテーションを使うべきか、ダブルクォーテーションを使うべきか
* 文字列をエスケープするには
* 文字列を連結するには
* 文字列と数値を連結できるかどうか
* 文字列の長さを調べるには
* 文字列内の特定位置の文字を調べるには
* 文字列から部分文字列を抽出するには
* 文字列の大文字・小文字を切り替えるには
* 文字列内の一部の文字列を別の文字列に置き換えるには
### 配列

* 配列を作成するには
* 配列内の要素を取得したり変更したりするには(多次元配列の場合についても含む)
* 配列の長さを調べるには
* 配列に要素を追加する、もしくは、配列から要素を削除するには
* 文字列を分割して配列にするには、もしくは配列を連結して一つの文字列にするには
### JavaScript のデバッグ

* 基本的なエラーの種類とは
* ブラウザー開発者ツールとは何か、どのように開くのか
* JavaScript コンソールに値を出力するには
* ブレイクポイント等の JavaScript のデバッグ機能を使うには

JavaScript のデバッグに関する詳細については、JavaScript のよくある問題を扱うを参照してください。よくあるエラーの説明についてはその他のよくあるエラーを参照してください。

### コード内での決定

* 変数の値やその他の条件によって異なるコードブロックのうちどれを実行するか決定するには
* if...else 文を使用するには
* 条件判定のブロックを別のブロックに入れ子にするには
* AND や OR、NOT を JavaScript で使用するには
* 多くの選択肢を一つの条件として手軽に扱うには
* true/false の判定によって 2 つの選択肢から 1 つを手早く選択するのに、三項演算子を使用するには
### ループ/イテレーション

* 同一のコード片を繰り返し実行するには
* 終了条件にマッチする前に、ループを終了させるには
* 次の繰り返し処理にスキップするには
* while ループ、do ... while ループを使用するには
* 配列内の要素を反復処理する方法
* 多次元配列の要素を反復処理する方法
* オブジェクト内のメンバーを反復処理する方法
* 配列内にネストされたオブジェクトのメンバーを反復処理する方法
中級のユースケース
---------

### 関数

* ブラウザー内での関数を調べるには
* 関数とメソッドの違いとは
* 独自の関数を作成するには
* 関数を呼び出すには
* 匿名関数とは
* 関数を実行するときに引数を指定するには
* 関数のスコープとは
* 戻り値とは何か、どのように戻り値を返すか
### オブジェクト

* オブジェクトを作成するには
* ドット記法とは
* 角括弧を用いた記法とは
* オブジェクトのメソッドやプロパティを取得、設定するには
* オブジェクトのコンテキストにおける `this` とは何か
* オブジェクト指向プログラミングとは
* コンストラクターやインスタンスとは何か、それらをどのように作成するか
* JavaScript でオブジェクトを作成する方法にはどのようなものがあるか
### JSON

* JSON の構造とは、JavaScript から JSON を読み取るには
* JSON ファイルをページに読み込むには
* JSON からテキストに変換するには、テキストから JSON に変換するには
### イベント

* イベントハンドラとは何か、どのように使うのか
* インラインイベントハンドラとは
* `addEventListener()` 関数は何をするものか、どのように使うのか
* 自分のページにイベントのコードを追加するのに、どの方法を使用すべきか
* イベントオブジェクトとは何か、どのように使うのか
* 既定のイベントの挙動を抑制するには
* ネストされた要素でどのようにイベントが発火するか(イベントの伝播、キャプチャ、バブリング)
* イベントのデリゲートとは何か、どのように動作するか
### オブジェクト指向 JavaScript

* オブジェクトのプロトタイプとは何か
* コンストラクタープロパティとは何か、どのように使用するか
* どのようにコンストラクターにメソッドを追加するか
* 継承元からメンバーを引き継いで新しいコンストラクターを作成するには
* JavaScript で継承を使用すべきときはいつか
### Web API

* JavaScript を使用して DOM を操作(要素の追加や削除)するには


JavaScript オブジェクト入門 - ウェブ開発を学ぶ

JavaScript オブジェクト入門
===================

JavaScript では、文字列や配列などの JavaScript のコア機能から、JavaScript の最上部に構築されたブラウザー API まで、ほとんどのものがオブジェクトです。関連する関数や変数を効率的なパッケージにカプセル化して、便利なデータコンテナーとして動作する独自のオブジェクトを作成することもできます。JavaScript のオブジェクト指向の性質を理解することは、言語に関する知識をさらに深め、より効率的なコードを書く場合に重要です。したがって、このモジュールを用意しました。ここではオブジェクトの理論と構文を詳しく説明し、独自のオブジェクトを作成する方法を見ていきます。

#### フロントエンドのウェブ開発者になりたい方へ

目標に向かって取り組むために必要な情報をすべて盛り込んだコースを用意しました。

**始めましょう**

前提条件
----

このモジュールを始める前に、HTML と CSS にいくらか精通している必要があります。JavaScript を始める前に HTML 入門と CSS 入門をひととおり学習することをオススメします。

また、JavaScript オブジェクトを詳細に調べる前に、JavaScript の基本についていくらか精通している必要があります。このモジュールを試す前に、JavaScript の第一歩 と JavaScript の構成要素を通して学習してください。

**メモ:** もしあなたが作業しているコンピューター、タブレット、その他の端末で自分でファイルを作れない場合は、JSBin や Glitch といったようなオンラインコーディングプログラムで (ほとんどの場合) 試すことができます。

ガイド
---

オブジェクトの基本

JavaScript オブジェクトについて記載している最初の記事では、基本的な JavaScript オブジェクト構文を見てみます。コースの初期段階で既に見た JavaScript の機能を再び見てみたり、すでに扱っている機能の多くは実際にオブジェクトであるという事実を繰り返し述べています。

オブジェクトプロトタイプ

プロトタイプは、JavaScript オブジェクトが互いに機能を継承するメカニズムであり、古典的なオブジェクト指向プログラミング言語の継承メカニズムとは異なる働きをします。この記事では、その違いを探り、プロトタイプチェーンの仕組みを説明し、prototype プロパティを使用して既存のコンストラクタにメソッドを追加する方法を見ていきます。

オブジェクト指向プログラミング

この記事では、「古典的」オブジェクト指向プログラミングの基本的な原則をいくつか説明し、JavaScript でのプロトタイプモデルとは異なるところを見ていきます。

JavaScript でのクラス

JavaScriptは、「古典的な」オブジェクト指向プログラムを実装したい人のためにいくつかの機能を提供しています。この記事では、これらの機能を説明します。

JSON データの操作

JavaScript Object Notation (JSON) は、JavaScript オブジェクト構文に基づいて構造化されたデータを表現するための標準のテキストベースのフォーマットであり、ウェブサイト上でデータを表現し、送信するために一般的に使用されます (すなわち、サーバーからクライアントへデータを送信して、その結果ウェブページ上に表示することができます)。これはとても良く見るものなので、この記事では、JSON を解析してその中のデータ項目にアクセスしたり、独自の JSON を記述したりするなど、JavaScript を使用して JSON を操作するために必要なことをすべて説明します。

オブジェクト構築の練習

これまでの記事では、基本的な JavaScript オブジェクトの理論と構文の詳細をすべて見てもらい、あなたには出発できるしっかりとした基本が与えられました。この記事では実践的なエクササイズを行い、もっと楽しい色とりどりの色付きのボールを作成するカスタム JavaScript オブジェクトを作る練習をしていきます。

評価
--

バウンスボールのデモに機能を追加する

この評価では、前の記事のバウンスボールデモを出発点として使用し、新しい興味深い機能を追加する予定です。

関連情報
----

Learn JavaScript

ウェブ開発者を目指す人のための優れたリソース - 短いレッスンとインタラクティブなテスト、自動評価によるガイドで、インタラクティブな環境で JavaScript を学ぶことができます。最初の 40 レッスンは無料で、少額の 1 回払いでこのコースの全容を利用することができます。


非同期 JavaScript - ウェブ開発を学ぶ

非同期 JavaScript
==============

このモジュールでは非同期 JavaScript に触れ、なぜそれが重要なのか、そして、潜在的なブロッキング処理（例えばサーバからリソースを取得する）に効果的に対処するためにどうやって使うのかを見ていきます。

#### フロントエンドウェブ開発者を目指す方へ

目標に向かって頑張るために必要な情報をまとめたコースをご用意しました。

**始めましょう**

前提条件
----

非同期 JavaScript はとても高度なトピックなので、事前に JavaScript の第一歩と JavaScript の構成要素のモジュールに取り組んでおくことをおすすめします。

**メモ:** ファイルを作成する手段のないコンピューター・タブレット・その他の端末をお使いの場合、（ほとんどの）コード例は JSBin や Glitch などのオンラインエディターでも試すことができます。

ガイド
---

非同期 JavaScript 入門

この記事では**同期**プログラミングと**非同期**プログラミングとは何か、なぜ頻繁に非同期のテクニックを使う必要があるのか、歴史的に非同期関数は JavaScript でどのように実装されてきたのか、そしてその問題点が何だったのかを見ていきます。

プロミスの使い方

ここではプロミスを紹介し、プロミスベースの API の使い方をお見せします。`async` と `await` キーワードの紹介もここで行います。

プロミスベースの API の実装

この記事では独自のプロミスベースの API を実装する方法を概説します。

ワーカー入門

ワーカーを使用すると、特定のタスクを別のスレッドで実行し、メインコードの応答性を維持することができます。この記事では、長時間実行される同期的な関数をワーカーを使用して書き直します。

学習の評価
-----

アニメーションを順番に再生する

この評価ではプロミスを使用して一連のアニメーションを特定の順序で再生してください。

関連情報
----

* Asynchronous Programming (Marijn Haverbeke 氏の非常に優れたオンライン書籍 Eloquent JavaScript より)


オブジェクト構築の練習 - ウェブ開発を学ぶ

オブジェクト構築の練習
===========

* 前のページ
* Overview: Objects
* 次のページ

ここまでの記事で JavaScript オブジェクトの根幹部に関する理論と文法の詳細についてすべてを見てきて、始めていくのに十分な基礎固めをしました。この記事では実練習を行ない、独自の JavaScript オブジェクトを作っていくための実践をしていきましょう — 楽しくてカラフルなものを。

|  |  |
| --- | --- |
| 前提知識: | 基礎的なコンピューターの知識、HTML と CSS への基本的な理解、基礎的な JavaScript の理解（JavaScript の第一歩と JavaScript の構成要素を参照）とオブジェクト指向 JavaScript の基本（JavaScript オブジェクトの基本を参照）。 |
| 目標: | オブジェクトの使い方とオブジェクト指向のテクニックを実世界のコンテストで練習する。 |

ボールを弾ませよう
---------

この記事では伝統的な「弾むボール」のデモを作ってみて、JavaScript でどれほどオブジェクトが役に立つかお見せしましょう。小さなボールは画面じゅうを跳ねまわり、それぞれがぶつかると色が変わります。完成したものはこんな風に見えることでしょう:

![Screenshot of a webpage titled "Bouncing balls". 23 balls of various pastel colors and sizes are visible across a black screen with long trails behind them indicating motion.](/ja/docs/Learn/JavaScript/Objects/Object_building_practice/bouncing-balls.png)

この例では画面にボールを描くのに キャンバス API を使い、画面をアニメーションさせるのに requestAnimationFrame を使います — これらの API について事前の知識は不要です。この記事を読み終わる頃にはこれら API についてもっと知りたくなっているだろうと期待してますが。道中では、イカしたオブジェクトを活用して、ボールを壁で弾ませる、それぞれがぶつかった事を判定する(**衝突判定**という呼び名で知られています)といった上手いテクニックをいくつかお見せしていきます。

始めに
---

始める前に `index.html`, `style.css`, と `main.js` ファイルのローカルコピーを作成してください。これらにはそれぞれ、以下が含まれています:

1. とても簡素な HTML 文書で、h1 要素と、ボールを描画するための `<canvas>` 要素と、この HTML に CSS と JavaScript を適用するための要素だけからなります。
2. とても簡単なスタイル、主には`<h1>`のスタイルとポジションを指定し、スクロールバーやページ端周辺のマージンを消す(素敵にきれいに見せるため)ためのもの。
3. `<canvas>`要素を設定し、これから使うことになる汎用の関数を提供する若干の JavaScript。

スクリプトの最初の部分はこのようになります。

```js
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

const width = (canvas.width = window.innerWidth);
const height = (canvas.height = window.innerHeight);
```

このスクリプトでは `<canvas>` 要素への参照を取得し、これに対して `getContext()` メソッドを使って描画していくためのコンテキストを取得します。得られる定数 (`ctx`) はキャンバスの描画可能領域を直接表現しており、ここに二次元の形状を書き込む事ができます。

次に `width` と `height` の 2 つの定数をセットし、キャンバス要素の幅と高さ(`canvas.width` と `canvas.height` プロパティで表わされます)をブラウザーのビューポートの幅と高さ(ウェブページが表示される領域です — `Window.innerWidth` と`Window.innerHeight` プロパティから取得できます)に等しくします。

変数の値をさっと全部同じにするのに、代入が連鎖していることに注意してください。これで全く問題ありません。

それから、2 つのヘルパー関数を設置します。

```js
function random(min, max) {
  return Math.floor(Math.random() \* (max - min + 1)) + min;
}

function randomRGB() {
  return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`;
}
```

`random()` 関数は、2 つの数値を引数に取り、その間の範囲の乱数を返します。`randomRGB()` 関数は、`rgb()` 文字列として表されるランダムな色を生成します。

プログラム用のボールを一つモデル化する
-------------------

我々のプログラムでは画面中を跳ねまわるたくさんのボールがあります。これらのボールはどれも同じルールで動くので、1 つのオブジェクトで表わすのが理に叶っています。まずはコードの最後に以下のクラス定義を追加するところから始めましょう。

```js
class Ball {
  constructor(x, y, velX, velY, color, size) {
    this.x = x;
    this.y = y;
    this.velX = velX;
    this.velY = velY;
    this.color = color;
    this.size = size;
  }
}
```

今のところ、このクラスにはコンストラクターだけが含まれており、このコンストラクターで、プログラム内で機能するために各ボールが必要とするプロパティを初期化することができます。

* `x`、`y`座標 — ボールが画面のどこからスタートするか表わす水平と垂直の座標。これは 0（画面左上隅）からブラウザービューポートの幅と高さの（画面右下隅）間の値を取ります。
* 水平と垂直方向の速度 (`velX` と `velY`) — 個々のボールには水平と垂直方向の速度が与えられます。実際にはアニメーションが開始されると、これらの値が `x`/`y`座標値に定期的に加算され、各フレームでこの値だけ移動していきます。
* `color` — 個々のボールには色がつけられます。
* `size` — 個々のボールには大きさがあります — ピクセルを単位とする半径で表わします。

これはプロパティを取り扱いましたが、メソッドはどうしましょうか？プログラムの中ではボールに実際に何かさせたいわけです。

### ボールを描画する

まず、以下の `draw()` メソッドを `Ball` クラスに追加しましょう。

```js
draw() {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 \* Math.PI);
  ctx.fill();
}
```

この関数を使って、以前定義した 2D キャンバスコンテキスト(`ctx`)のメンバーを順に呼び出す方法で、ボール自身が画面に自分を描画する方法を教え込みます。コンテキストは紙のようなもので、ペンを使って何か描くように指示したいわけです:

* まずは、`beginPath()` を使って紙に形を描きたいと宣言します。
* 次に `fillStyle` を使って形を何色にしたいか宣言します — ここではボールの `color` プロパティを指定します。
* 次に `arc()` メソッドを使って紙に円弧形をなぞります。これの引数は:
    + 円弧の中心座標、`x` と `y` — ボールの `x`、`y` プロパティを指定します。
    + 円弧の半径 — ここではボールの `size` プロパティです。
    + 最後の二つの引数は円弧の開始点から終了点までの角度を円の中心角で指定します。ここでは 0 度から `2 * PI`、これはラジアンで表わした 360 度に相当します(ややこしいですがラジアンで指定しなければなりません)。これで一周した円を描けます。もし `1 * PI` までしか指定しなければ、半円(180 度)になるでしょう。
* 最後の最後に、`fill()` (en-US) メソッドを使って、これはおおよそ、「`beginPath()` から描き始めた線描を終了し、描いた領域を前に `fillStyle` で指定していた色で塗り潰せ」という指示になります。

これでオブジェクトをテストしてみられるようになりました。

1. コードを保存し、HTML ファイルをブラウザーで読み込みます。
2. ブラウザーの JavaScript コンソールを開いて、ページを再読み込みし、キャンバスのサイズがコンソール分小さくなったビューポート領域に合うようにします。
3. 次をタイプして、新しいボールのインスタンスを作成します:

```js
const testBall = new Ball(50, 100, 4, 4, "blue", 10);
```

4. そのメンバを呼び出して見てください。

```js
testBall.x;
testBall.size;
testBall.color;
testBall.draw();
```

5. 最後の行を入力すると、キャンバスのどこかにボールが表示されたはずです。
### ボールのデータの更新

ボールの位置を描画することはできますが、実際にボールを移動させるには、何らかの更新関数が必要です。以下のコードを `Ball` のクラス定義の中に追加してください。

```js
update() {
  if ((this.x + this.size) >= width) {
    this.velX = -(this.velX);
  }

  if ((this.x - this.size) <= 0) {
    this.velX = -(this.velX);
  }

  if ((this.y + this.size) >= height) {
    this.velY = -(this.velY);
  }

  if ((this.y - this.size) <= 0) {
    this.velY = -(this.velY);
  }

  this.x += this.velX;
  this.y += this.velY;
}
```

関数の頭から 4 つの部分でボールがキャンバスの端に達したかどうかチェックします。もしそうであれば、関連する速度の向きを反転してボールが反対の向きに移動するようにします。つまり例えば、ボールが上方向に移動していた（`velY` が負）ならば、垂直方向の速度をボールが下方向に移動するように（`velY` を正に）変更します。

4 つの場合で、次のことを確認しています。

* `x` 座標がキャンバスの幅より大きいか (ボールは右端から飛び出そうとしている)
* `x` 座標が 0 より小さいか (ボールは左端から飛び出そうとしている)
* `y` 座標がキャンバスの高さより大きいか (ボールは下端から飛び出そうとしている)
* `y` 座標が 0 より小さいか (ボールは上端から飛び出そうとしている)

それぞれの場合で計算にボールの `size` を含めていますが、これは `x`/`y` 座標はボールの中心ですが、ボールの端のところで周囲から跳ね返って欲しいからです — 跳ね返る前に画面外にめり込んで欲しくないからです。

最後の二行では `velX` を `x` 座標に、`velY` を `y` 座標に加算しています — 結果ボールはこのメソッドが呼ばれる毎に移動します。

とりあえずはここまでで、ちょいとアニメーションさせてみよう!

ボールのアニメーション
-----------

さあ、楽しい事をやりましょう。では、キャンバスにボールを追加し、アニメーションさせるところから始めましょう。

最初に、ボールを全部保存しておく場所がどこかに必要です。以下がこれをやってくれます — あなたのコードの最後に追加してください:

```js
const balls = [];

while (balls.length < 25) {
  const size = random(10, 20);
  const ball = new Ball(
    // ball position always drawn at least one ball width
    // away from the edge of the canvas, to avoid drawing errors
    random(0 + size, width - size),
    random(0 + size, height - size),
    random(-7, 7),
    random(-7, 7),
    randomRGB(),
    size,
  );

  balls.push(ball);
}
```

`while` ループは、 `random()` および `randomRGB()` 関数で作成したランダムな値を使って新しい `Ball()` のインスタンスを作成し、ボールの配列の後ろに `push()` して追加していきますが、これは配列中のボールの数が 25 に満たない間まで繰り返されます。`balls.length < 25` の数字をいろいろ変えれば、配列の中のボールの数を増やしたり減らしたりできます。コンピューターとブラウザーの処理能力によりますが、ボールを数千にするとアニメーションはかなり遅くなります! 注意してね。

次に、以下をあなたのコードの末尾に追加してください。

```js
function loop() {
  ctx.fillStyle = "rgba(0, 0, 0, 0.25)";
  ctx.fillRect(0, 0, width, height);

  for (const ball of balls) {
    ball.draw();
    ball.update();
  }

  requestAnimationFrame(loop);
}
```

ものをアニメーションさせるすべてのプログラムには、大概アニメーションループがあり、プログラム内の情報を更新して、アニメーションの各フレームでその結果を表示します。これは大半のゲームや類似するプログラムの基本になります。コード中の `loop()` 関数は以下の事を行ないます:

* キャンバスの塗り潰し色を半透明の黒にし、その色でキャンバスの幅と高さいっぱいの長方形を `fillRect()` で描きます(これの 4 つの引数は始点の座標と、描画する長方形の幅と高さになります)。これで次のフレームを描く前に、前のフレームで描いた内容を見えなくします。これをしないと、ボールじゃなくて長い蛇がキャンバスの中を這い回る様を見る事になります! 塗り潰す色は半透明の `rgba(0,0,0,0.25)` なので、以前の何フレーム分かがかすかに残り、ボールが移動した後の軌跡を表現します。もし 0.25 を 1 に変更すると、軌跡は全く見えなくなります。この値を変えて、どんな効果になるか見てみてください。
* ループで `balls`配列のボール全部をなめてそれぞれのボールの `draw()` と `update()` 関数を実行し、それぞれを画面に描画してから、次のフレームに備えて必要な位置と速度の更新を行います。
* この関数を `requestAnimationFrame()` メソッドを使って再実行します — このメソッドが繰り返し実行され同じ関数名を与えられると、その関数がスムースなアニメーションを行なうために毎秒設定された回数実行されます。これはたいてい再帰的に行われます — つまり関数は毎回その関数自身を呼び出すので、何度も何度も繰り返し実行されます。

最後に、コードの最後に次の行を追加します — アニメーションを開始するために、一旦は関数を呼ぶ必要があるのです。

```js
loop();
```

基本としてはこんなところ — 保存して再読み込みし、ボールがはずむのをテストしてみてください。

衝突検出の追加
-------

さあ、もうちょっと面白くするため、プログラムに衝突判定を追加して、ボールに他のボールとぶつかったらどうするのか教えましょう。

まず、`Ball` クラスに以下のようなメソッド定義を追加します。

```js
collisionDetect() {
  for (const ball of balls) {
    if (this !== ball) {
      const dx = this.x - ball.x;
      const dy = this.y - ball.y;
      const distance = Math.sqrt(dx \* dx + dy \* dy);

      if (distance < this.size + ball.size) {
        ball.color = this.color = randomRGB();
      }
    }
  }
}
```

このメソッドはちょっとばかり複雑なので、今はどんな動作をしているのか正確に理解できなくても構いません。説明していきます。

* それぞれのボールで、他のボールそれぞれとこのボールが衝突していないか調べなければなりません。そのため、別な `for...of` を開始し、`balls[]` 配列内のすべてのボールを回します。
* 内側のループに入ってすぐ、`if` 文でループで回しているボールがチェックしているボールと同じか調べています。ボールがそれ自体とぶつかっているかチェックしたくないですから! これのために、現在のボール（collisionDetect メソッドが実行されているボールです）がループ中のボール（現在の collisionDetect メソッド内のループのくりかえし中で参照されているボール）と一致しているかチェックします。`!` を使って等価性チェックを逆にしているので、`if` 文の中のコードはボールが**同じでない**ときだけ実行されます。
* そして二つの円が衝突していないか調べるための一般的なアルゴリズムを使っています。基本的には円ないの領域が重なっているかチェックしています。これについて詳しくは 2 次元の衝突判定で解説されています。
* もし衝突が検出されたら、内側の `if` 文の中のコードが実行されます。この場合では、両方のボールの `color` プロパティをランダムな新しい色に設定しているだけです。もっと複雑なこと、現実っぽくボールを互いに跳ね返らせたりもできたでしょうが、これを実装したとするともっとずっとに複雑なったでしょう。そのような物理シミュレーションには、PhysicsJS, matter.js, Phaser などのゲームや物理用のライブラリーを使う開発者が多いです。

アニメーションの各フレーム毎にこのメソッドを呼び出さなければなりません。`loop()` 関数を更新して、`ball.collisionDetect()` を `ball.update()` の後に呼び出すようにします。

```js
function loop() {
  ctx.fillStyle = "rgba(0, 0, 0, 0.25)";
  ctx.fillRect(0, 0, width, height);

  for (const ball of balls) {
    ball.draw();
    ball.update();
    ball.collisionDetect();
  }

  requestAnimationFrame(loop);
}
```

デモを保存して再読み込みし、ボールがぶつかった時に色が変わるのを見てください。

**メモ:** この例題を動かすのに困った時は、あなたの JavaScript コードを私たちの完成版と比べてみてください（ライブ実行版も見られます）。

まとめ
---

自分版の実世界で跳ね回るランダムボール例作り、この全単元で出てきた様々なオブジェクトやオブジェクト指向テクニックを使ったものをあなたに楽しんでいただけていれば、と思います。オブジェクトの実践的な使い方の練習や、実世界のコンテキストについて得られるものがあったはずです。

オブジェクトに関する記事は以上です — 残るのは、あなが自分のスキルをオブジェクトの評価問題で試してみる事だけです。

関連情報
----

* キャンバスのチュートリアル — 2D キャンバスの初心者向けガイド。
* requestAnimationFrame()
* 二次元の衝突検出
* 三次元の衝突検出
* 純粋な JavaScript を使用した 2D ブロック崩しゲーム — 2D ゲームの作り方に関する、素晴しい初心者向けチュートリアル。
* Phaser を使用した 2D ブロック崩しゲーム — JavaScript ゲームライブラリーを使って 2D ゲームを作るための基本を解説しています。
* 前のページ
* Overview: Objects
* 次のページ


JavaScript オブジェクトの基本 - ウェブ開発を学ぶ

JavaScript オブジェクトの基本
====================

* Overview: Objects
* 次のページ

この記事では、基本的な JavaScript オブジェクトの構文を学び、このコースで以前に見た一部の JavaScript の機能を復習し、すでに提供された多くの機能がオブジェクトであるという事実を再確認します。

|  |  |
| --- | --- |
| 前提知識: | 基本的なコンピューターリテラシー、基本的な HTML と CSS に対する理解、基本的な JavaScript に親しんでいること（JavaScript の第一歩とJavaScript の構成要素を参照してください）。 |
| 目標: | オブジェクト指向プログラミングについての基本的な理論、どのように JavaScript に関連するか、JavaScript の作業を始める方法を理解できること。 |

オブジェクトの基本
---------

 オブジェクトとは、関連するデータや 機能の集合体です。
 これらは通常、いくつかの変数や関数（オブジェクトの中にある場合はプロパティやメソッドと呼ばれる）で構成されています。
 見ていくうちに理解できるように、例を挙げてみましょう。

最初に oojs.html ファイルを手元にコピーしてください。このファイルにはちょっとした内容 — ソースコードを書き込むための `<script>` 要素が一つ含まれています。このファイルをオブジェクトを書くための元として使います。作業中は開発者ツールの JavaScript コンソールを開いておいて、すぐにコマンドを入力できるようにしておくとよいでしょう。

他の JavaScript の書き方と同じように、オブジェクトの生成は変数の宣言と初期化から始まります。手始めに、ファイルにある JavaScript コードの下に次のものを書いてみてください。それから保存して再読み込みしましょう。

```js
const person = {};
```

ブラウザーの JavaScript コンソールを開いて、`person` と入力して、 `Enter`/`Return` を押してください。以下のいずれかの行に似た結果が得られるはずです。
```

[object Object]
Object { }
{ }
```

おめでとうございます。最初のオブジェクトが作成されました。成功です！しかし、これは空のオブジェクトなので、実際に使用することはできません。ファイル内の JavaScript オブジェクトを次のように更新してみましょう。

```js
const person = {
  name: ["Bob", "Smith"],
  age: 32,
  bio: function () {
    console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`);
  },
  introduceSelf: function () {
    console.log(`Hi! I'm ${this.name[0]}.`);
  },
};
```

保存して更新した後、ブラウザーの開発者ツールの JavaScript コンソールに以下いくつか入力してみてください：

```js
person.name;
person.name[0];
person.age;
person.bio();
// "Bob Smith is 32 years old."
person.introduceSelf();
// "Hi! I'm Bob."
```

オブジェクトから、データと機能を追加することができました。これで簡単な書き方で情報が引き出せます。

さて、何が起きているのでしょうか。オブジェクトには複数のメンバーがあり、それぞれに名前がついていて(例えば上の例では `name` や `age`)、それぞれに値 (`['Bob', 'Smith']` や `32`) があります。それぞれの名前と値の組はカンマ ( , ) で区切られていて、名前と値はコロン ( : ) で区切られています。常にそのように書きます。

```js
const objectName = {
  member1Name: member1Value,
  member2Name: member2Value,
  member3Name: member3Value,
};
```

メンバーの値はほとんど何でも大丈夫です。例えば、先ほどの例では文字列、数値、2 つの配列に 2 つの関数でした。最初の 4 つはデータ項目でそのオブジェクトの**プロパティ**と呼ばれます。後ろの 2 つはオブジェクトの持つデータを使用して何かをする関数でオブジェクトの**メソッド**と呼ばれます。

オブジェクトのメンバーが関数である場合、よりシンプルな構文があります。`bio: function ()` の代わりに `bio()` と書けばよいのです。次のようにします。

```js
const person = {
  name: ["Bob", "Smith"],
  age: 32,
  bio() {
    console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`);
  },
  introduceSelf() {
    console.log(`Hi! I'm ${this.name[0]}.`);
  },
};
```

これ以降は、この短い構文を使用することにします。

このようなオブジェクトは**オブジェクトリテラル**と呼ばれ、作成することになったオブジェクトのコンテンツを文字通り書き出したものです。これは、後で見ていくクラスからインスタンス化されたオブジェクトとは異なる形で表現されています。

オブジェクトリテラルを使用してオブジェクトを作成するのは、構造化された関連のある一連のデータアイテムを何らかの方法で転送したい場合、例えば、データベースに入れるリクエストをサーバーに送信するような場合にとても一般的です。単一のオブジェクトを送信することは、複数のアイテムを個別に送信するよりもはるかに効率的であり、個々のアイテムを名前で識別したい場合には、配列よりも扱いやすいときがあります。

ドット記法
-----

先ほどの例では、オブジェクトのプロパティとメソッドに対して、**ドット記法**を用いてアクセスしました 。オブジェクト名 (person) は**名前空間**として機能します。オブジェクト内に**カプセル化**されたものにアクセスするには、まずこのオブジェクト名を入力する必要があります。次に、ドット ( . ) を書いて、それからアクセスしたい項目を記述します。項目になりうるのは、単純なプロパティの名前や、配列の要素や、そのオブジェクトのメソッドの 1 つへの呼び出しなどです。次に例を示します:

```js
person.age;
person.bio();
```

### オブジェクトプロパティとしてのオブジェクト

オブジェクトの内部にさらにほかのオブジェクトを持つことも可能です。例えば、先の例で、`name` メンバーを、

```js
const person = {
  name: ["Bob", "Smith"],
};
```

以下のように変更してみましょう。

```js
const person = {
  name: {
    first: "Bob",
    last: "Smith",
  },
  // …
};
```

これらのアイテムにアクセスするには、余分な手順を別のドットで終わりにつなげる必要があります。JS コンソールで試してみてください。

```js
person.name.first;
person.name.last;
```

この時点で下の書き方をしていたところは、以下のように変えなければなりません。

```js
name[0];
name[1];
```

を、

```js
name.first;
name.last;
```

のようにしなければ、メソッドが動かなくなってしまうでしょう。

ブラケット記法
-------

 ブラケット記法は、オブジェクトのプロパティにアクセスするための別の方法を提供します。
 次のようにドット記法を使用する代わりに、

```js
person.age;
person.name.first;
```

角括弧を使用して次のようにすることができます。

```js
person["age"];
person["name"]["first"];
```

 これは配列のアイテムにアクセスする方法ととても似ていて、基本的には同じことです。アイテムを選択するためにインデックス番号を使用する代わりに、各メンバーの値に関連付けられた名前を使用しているのです。
 オブジェクトが**連想配列**と呼ばれるのも当然で、配列が数値と値を対応付けるのと同じように、文字列と値を対応付けます。

 一般に、ドット記法はブラケット記法よりも簡潔で読みやすいため、より好ましいとされています。
 しかし、角括弧を使用しなければならない用途もあります。
 例えば、オブジェクトのプロパティ名が変数で管理されている場合、ドット記法を使用して値にアクセスすることはできませんが、ブラケット記法を使用して値にアクセスすることは可能です。

下記の例では、`logProperty()` 関数は `person[propertyName]` を使用して `propertyName` で指定されたプロパティの値を取得することができる。

```js
const person = {
  name: ["Bob", "Smith"],
  age: 32,
};

function logProperty(propertyName) {
  console.log(person[propertyName]);
}

logProperty("name");
// ["Bob", "Smith"]
logProperty("age");
// 32
```

オブジェクトメンバーの設定
-------------

今まではオブジェクトメンバーからの引き出す (**取得する**) 方法だけを見てきましたが、値を設定するメンバーを宣言することで、オブジェクトのメンバーに値を**設定** (更新) することもできます。(ドットを使用した書き方でも、角括弧を使用した書き方でも構いません。)

```js
person.age = 45;
person["name"]["last"] = "Cratchit";
```

これらの行を入力してみて、実際に値が変わったか調べてみましょう。

```js
person.age;
person["name"]["last"];
```

メンバーの値を設定するのは存在するプロパティやメソッドの更新だけにはとどまりません。まったく新しいメンバーを追加することもできるのです。JS コンソールで次のものを試してみてください。

```js
person["eyes"] = "hazel";
person.farewell = function () {
  console.log("Bye everybody!");
};
```

新しいメンバーが追加されたことを確認してみましょう。

```js
person["eyes"];
person.farewell();
// "Bye everybody!"
```

ブラケット記法の良いところは、動的にメンバーの値を設定できるだけでなく、メンバーの名前も追加できるところです。例えば、ユーザーの情報として 2 つのテキストフィールドに名前と値を入力してもらい、人により個別のデータを設定したいとします。そういった値を以下のように取得します。

```js
const myDataName = nameInput.value;
const myDataValue = nameValue.value;
```

そうして、取得したメンバー名と値を次のように `person` オブジェクトに設定します。

```js
person[myDataName] = myDataValue;
```

この動作を確認するため、先ほどのコードの `person` オブジェクトの中括弧に続いて、次の行をコードに追加してみてください。

```js
const myDataName = "height";
const myDataValue = "1.75m";
person[myDataName] = myDataValue;
```

そして、保存して再度読み込んで、次の行をテキストボックスに入力してみてください。

```js
person.height;
```

上記の方法を使用してオブジェクトにプロパティを追加することは、ドット記法ではできません。ドット記法は、名前を指す変数ではなく、書いたとおりのメンバー名のみ受け入れることができます。

"this" とは何か
-----------

メソッドの中で、少し見慣れない点に気付いたかもしれません。 次の例でその点について考えてみましょう。

```js
introduceSelf() {
  console.log(`Hi! I'm ${this.name[0]}.`);
}
```

"this" とは何だろうと思ったことでしょう。 この `this` キーワードはコードの中がその中で書かれている、現在のオブジェクトを参照しています。なので、この場合では `person` を指します。 なぜ `this` の代わりに単に `person` と書かないのでしょうか。

まあ、オブジェクトリテラルを単一のものしか作成しない場合は、それほど有益なものではありません。しかし、複数のオブジェクトを作成する場合、`this`を使用すると、作成するすべてのオブジェクトに対して同じメソッド定義を使用することができます。

それでは、簡略化した `person` オブジェクトを使って、その意味を説明していきましょう。

```js
const person1 = {
  name: "Chris",
  introduceSelf() {
    console.log(`Hi! I'm ${this.name}.`);
  },
};

const person2 = {
  name: "Deepti",
  introduceSelf() {
    console.log(`Hi! I'm ${this.name}.`);
  },
};
```

この場合、`person1.introduceSelf()` は "Hi! I'm Chris." を出力します。一方、`person2.introduceSelf()` は "Hi! I'm Deepti." を出力します。しかし、どちらの場合も、そのメソッド部分のコードは全く同じです。これは、オブジェクトリテラルを手書きするときにはあまり有益ではありませんが、**コンストラクター**を使用して単一のオブジェクト定義から複数のオブジェクトを作成するようになったときには不可欠なものとなります（これが次の節の主題です）。

コンストラクターの導入
-----------

オブジェクトリテラルを使用するのは、1つのオブジェクトを作成するだけなら問題ありませんが、前回の節のように複数のオブジェクトを作成する必要がある場合は、非常に不十分です。オブジェクトを作成するたびに同じコードを書かなければならないし、オブジェクトのプロパティを変更したい場合（たとえば`height`プロパティを追加したい場合）には、すべてのオブジェクトを更新することを忘れてはなりません。

オブジェクトの「形」、つまりオブジェクトが持つことのできるメソッドやプロパティの集合を定義して、好きなだけオブジェクトを作成し、異なるプロパティの値だけを更新する方法が欲しいところです。

最初のバージョンは、単なる関数です。

```js
function createPerson(name) {
  const obj = {};
  obj.name = name;
  obj.introduceSelf = function () {
    console.log(`Hi! I'm ${this.name}.`);
  };
  return obj;
}
```

この関数は、呼び出すたびに新しいオブジェクトを作成し、返します。オブジェクトは 2 つのメンバーを持つことになります。

* プロパティ `name`
* メソッド `introduceSelf()`

`createPerson()` は `name` プロパティの値を設定するために `name` という引数を取りますが、`introduceSelf()` メソッドの値はこの関数で作成したすべてのオブジェクトで同じになることに注意してください。これは、オブジェクトを作成する際にとてもよくあるパターンです。

これで、定義を再利用して、好きなだけオブジェクトを作成することができます。

```js
const salva = createPerson("Salva");
salva.name;
salva.introduceSelf();
// "Hi! I'm Salva."

const frankie = createPerson("Frankie");
frankie.name;
frankie.introduceSelf();
// "Hi! I'm Frankie."
```

これはうまくいくのですが、少し時間がかかります。空のオブジェクトを作成し、初期化して、それを返す必要があります。より良い方法は、**コンストラクター**を使用することです。コンストラクターとは、`new` キーワードを使って呼び出される関数に過ぎません。コンストラクターを呼び出すと、次のようなことが行われます。

* 新しいオブジェクトを作成する
* 新しいオブジェクトに `this` を結び付け、コンストラクターのコードで `this` を参照することができるようにする
* コンストラクターでコードを実行する
* その新しいオブジェクトを返す

コンストラクターは、慣習上、大文字で始められ、作成するオブジェクトの種類に応じた名前を付けます。したがって、例えばを次のように書き換えることができます。

```js
function Person(name) {
  this.name = name;
  this.introduceSelf = function () {
    console.log(`Hi! I'm ${this.name}.`);
  };
}
```

`Person()` をコンストラクターとして呼び出すには `new` を使用します。

```js
const salva = new Person("Salva");
salva.name;
salva.introduceSelf();
// "Hi! I'm Salva."

const frankie = new Person("Frankie");
frankie.name;
frankie.introduceSelf();
// "Hi! I'm Frankie."
```

ずっとオブジェクトを使ってきた
---------------

これらの例を通して、既に使ってきたドット記述ととても似ていると考えたかもしれません。なぜならこのコースを通してそのような方法を使用してきたからです。組み込みのブラウザー API や JavaScript オブジェクトを使う例への取り組みを通して、いつもオブジェクトを使用してきました。なぜならそのような機能は、基本的なカスタム例よりも複雑ではありますが、ここまで見てきたものと全く同種のオブジェクト構造を使うことで構築されているからです。

だから、このように文字列のメソッドを使うと、

```js
myString.split(",");
```

`String` オブジェクトのインスタンスで利用できるメソッドを使用していたのです。コードの中で文字列を作成するときにはいつでも、その文字列は自動的に `String` のインスタンスとして生成されます。そしてそのために、いくつかの共通なメソッドやプロパティを使用することができます。

次の行のようにドキュメントオブジェクトモデルにアクセスするときは、

```js
const myDiv = document.createElement("div");
const myVideo = document.querySelector("video");
```

`Document` オブジェクトのインスタンスで使用可能なメソッドを使っていました。それぞれのウェブページが読み込まれるたびに、`document` と呼ばれる `Document` のインスタンスが作られ、それはウェブページ全体の構造、コンテンツ、その URL 等その他の機能を表現します。もう一度述べますが、これはいくつかの共通なメソッドやプロパティを使用できることを意味します。

今まで使用してきた、`Array` や `Math` などの、他の多くの組み込みのオブジェクトや API でも全く同じです。

組み込みのオブジェクトと API では、常に自動でオブジェクトのインスタンスが生成される訳ではないことを注意してください。例えば、現代のブラウザーがシステム通知を発行することを許可する通知 API では、発行したい各通知のためにコンストラクターを使用した新しいオブジェクトを生成する必要があります。JavaScript コンソールに次のように入力してみてください。

```js
const myNotification = new Notification("Hello!");
```

スキルテスト
------

この記事の最後に達しましたが、最も大切な情報を覚えていますか？次に進む前に、この情報が身に付いたかどうかを確認するテストがあります。Test your skills: Object basics を見てください。

おさらい
----

お疲れ様でした。最初の JS オブジェクトの記事の終わりまで到達しました。JavaScript のオブジェクトがどのように機能するかについて、良い考えを得ることができたのではないでしょうか。記事では、簡単なオリジナルオブジェクトの作成を含んでいました。オブジェクトは関連するデータと機能を保存する構造として非常に便利であることも理解しなければいけません。もし別々の変数と関数として、`person` オブジェクトのすべてのプロパティとメソッドを記録していくとすると、非効率でありストレスが溜まります。そして同じ名前の他の変数や関数をクラッシュしてしまう危険性も抱えてしまいます。オブジェクトは有害な方法を避けて、パッケージの中で安全に鍵をして情報を守ってくれます。

次の記事では、**プロトタイプ**について見ていきます。これは、JavaScript がオブジェクトに他のオブジェクトのプロパティを継承させるための基本的な方法です。

* Overview: Objects
* 次のページ


オブジェクトのプロトタイプ - ウェブ開発を学ぶ

オブジェクトのプロトタイプ
=============

* 前のページ
* Overview: Objects
* 次のページ

プロトタイプは、JavaScript オブジェクトが他のものから機能を継承する仕組みです。この記事では、プロトタイプとは何か、プロトタイプチェーンの動作方法、オブジェクトのプロトタイプを設定するにはどうすればよいかを解説していきます。

|  |  |
| --- | --- |
| 前提条件: | JavaScript 関数の理解、JavaScript の基礎知識（JavaScript の第一歩とJavaScript の構成要素を参照）、OOJS の基礎（オブジェクトの基本を参照）。 |
| 目標: | JavaScript のオブジェクトのプロトタイプ、プロトタイプチェーンの動作方法、prototype プロパティに新しいメソッドを追加する方法を理解する。 |

プロトタイプチェーン
----------

ブラウザーのコンソールで、オブジェクトリテラルを作成してみてください。

```js
const myObject = {
  city: "Madrid",
  greet() {
    console.log(`Greetings from ${this.city}`);
  },
};

myObject.greet(); // Greetings from Madrid
```

これは、1 つのデータプロパティ `city` と 1 つのメソッド `greet()` を持つオブジェクトです。オブジェクトの名前の後にピリオドを付けて `myObject.` のようにコンソールに入力すると、このオブジェクトで利用できるすべてのプロパティのリストがポップアップ表示されます。`city`と `greet` だけでなく、他にもたくさんのプロパティがあることがわかると思います。
```

__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
valueOf
```

それらのうちの 1 つにアクセスしてみます。

```js
myObject.toString(); // "[object Object]"
```

これはうまくいきます（たとえ `toString()` が何をするのかが明らかでないとしても）。

これらの追加のプロパティは何でしょうか、そしてそれはどこから来ているのでしょうか？

JavaScript ですべてのオブジェクトは、その**プロトタイプ**と呼ばれる組み込みプロパティを持っています。プロトタイプはそれ自体がオブジェクトなので、プロトタイプは自分自身でプロトタイプを持ち、**プロトタイプチェーン**と呼ばれるものを持ちます。自分自身でプロトタイプに`null`を持つプロトタイプに到達すると、その連鎖は終わります。

**メモ:** オブジェクトのプロトタイプを指し示すプロパティは `prototype` という名前では**ありません**。その名前は標準ではありませんが、実際にはすべてのブラウザーが `__proto__` を使用しています。オブジェクトのプロトタイプにアクセスする標準的な方法は `Object.getPrototypeOf()` メソッドです。

オブジェクトのプロパティにアクセスしようとしたとき、オブジェクト自身にプロパティが見つからない場合は、プロトタイプを検索してプロパティを探します。それでもプロパティが見つからない場合は、プロトタイプのプロトタイプが検索され、プロパティが得られるか、チェーンの終わりに達するか、その場合は `undefined` を返すまで、そのような具合に繰り返します。

つまり、`myObject.toString()` を呼び出すと、ブラウザーは、

* `toString` を `myObject` で探します。
* 見つからない場合は、`myObject` のプロトタイプオブジェクトで `toString` を探します。
* 見つかったら、それを呼び出します。

`myObject` のプロトタイプは何でしょうか？それを探すには、 `Object.getPrototypeOf()` 関数を使用することができます。

```js
Object.getPrototypeOf(myObject); // Object { }
```

これは `Object.prototype` と呼ばれるオブジェクトで、既定ではすべてのオブジェクトが持つ、最も基本的なプロトタイプです。 `Object.prototype` のプロトタイプは `null` であり、プロトタイプの連鎖の終わりにあります。

![myObject のプロトタイプチェーン](/ja/docs/Learn/JavaScript/Objects/Object_prototypes/myobject-prototype-chain.svg)

オブジェクトのプロトタイプは常に `Object.prototype` であるとは限りません。次のようになってみてください。

```js
const myDate = new Date();
let object = myDate;

do {
  object = Object.getPrototypeOf(object);
  console.log(object);
} while (object);

// Date.prototype
// Object { }
// null
```

このコードでは、`Date` オブジェクトを作成し、プロトタイプの連鎖をたどって、プロトタイプをログ出力しています。このコードでは、`myDate` のプロトタイプは `Date.prototype` オブジェクトであり、*その* プロトタイプは `Object.prototype` であることを示します。

![Prototype chain for myDate](/ja/docs/Learn/JavaScript/Objects/Object_prototypes/mydate-prototype-chain.svg)

実際、`myDate2.getMonth()`のような馴染みのあるメソッドを呼び出す場合、`Date.prototype`で定義されたメソッドを呼び出していることになります。

プロパティのシャドウ化
-----------

オブジェクトにプロパティを定義した場合、そのオブジェクトのプロトタイプに同じ名前のプロパティが定義されているとどうなるのでしょうか。見てみましょう。

```js
const myDate = new Date(1995, 11, 17);

console.log(myDate.getYear()); // 95

myDate.getYear = function () {
  console.log("something else!");
};

myDate.getYear(); // 'something else!'
```

これは、プロトタイプチェーンの説明から予想できることです。`getYear()` を呼び出すと、ブラウザーはまず `myDate` にその名前のプロパティがないか探し、`myDate` で定義されていない場合にのみプロトタイプを調べます。つまり、`myDate` に `getYear()` を追加すると、`myDate` のバージョンが呼ばれることになります。

これはプロパティの「シャドウ化」と呼ばれます。

プロトタイプの設定
---------

JavaScript でオブジェクトのプロトタイプを設定する様々な方法があります。ここでは `Object.create()` とコンストラクターの 2 つの方法について説明します。

### Object.create の使用

`Object.create()` メソッドは、新しいオブジェクトを作成し、新しいオブジェクトのプロトタイプとして使用するオブジェクトを指定することができます。

以下に例を示します。

```js
const personPrototype = {
  greet() {
    console.log("hello!");
  },
};

const carl = Object.create(personPrototype);
carl.greet(); // hello!
```

ここでは、`greet()` メソッドを持つオブジェクト `personPrototype` を作成しています。次に、`Object.create()` を使用して、`personPrototype` をプロトタイプとする新しいオブジェクトを作成します。これで、新しいオブジェクトに対して `greet()` を名付けることができ、プロトタイプはその実装を提供することになります。

### コンストラクターの使用

JavaScript では、すべての関数が `prototype` という名前のプロパティを持っています。関数をコンストラクターとして呼び出すと、このプロパティが新しく構築されるオブジェクトのプロトタイプとして設定されます（規約では `__proto__` というプロパティに設定されています）。

つまり、コンストラクターの `prototype` を設定すれば、そのコンストラクターで作成するすべてのオブジェクトに、確実にそのプロトタイプを持たせるすることができます。

```js
const personPrototype = {
  greet() {
    console.log(`hello, my name is ${this.name}!`);
  },
};

function Person(name) {
  this.name = name;
}

Object.assign(Person.prototype, personPrototype);
// または
// Person.prototype.greet = personPrototype.greet;
```

ここでは次のものを生成します。

* `personPrototype` オブジェクト。これは `greet()` メソッドを持っています
* `Person()` コンストラクター関数。作成する人物の名前を初期化します。

次に、`personPrototype` で定義したメソッドを `Person` 関数の `prototype` プロパティに Object.assign で記述しています。

このコードの後、`Person()`を使用して作成したオブジェクトは、そのプロトタイプとして `Person.prototype` を取得し、その中に `greet` メソッドが自動的に格納されます。

```js
const reuben = new Person("Reuben");
reuben.greet(); // hello, my name is Reuben!
```

これは、先ほど `myDate` のプロトタイプが `Date.prototype` と呼ばれる理由も説明します。これは `Date` コンストラクターの `prototype` プロパティです。

### 独自プロパティ

上記の `Person` コンストラクターを使用して作成したオブジェクトは、2 つのプロパティを持ちます。

* `name` プロパティはコンストラクターで設定されるため、`Person` オブジェクトに直接現れます。
* `greet()` メソッドは、プロトタイプに設定されています。

メソッドはプロトタイプで定義し、データプロパティはコンストラクターで定義する、というパターンはよく見かけます。これは、メソッドは作成するオブジェクトごとに同じものを使うのが普通ですが、データプロパティはオブジェクトごとに自分自身で値を示したい場合が多いからです（人ごとに名前が違うようのと似ています）。

ここでいう `name` のように、オブジェクトに直接定義するプロパティは**独自プロパティ**と呼ばれ、あるプロパティが独自プロパティであるかどうかは静的メソッド `Object.hasOwn()` を使って調べることができます。

```js
const irma = new Person("Irma");

console.log(Object.hasOwn(irma, "name")); // true
console.log(Object.hasOwn(irma, "greet")); // false
```

**メモ:** ここでは静的でない `Object.hasOwnProperty()` メソッドを用いることもできますが、できれば `Object.hasOwn()` を用いることをお勧めします。

プロトタイプと継承
---------

プロトタイプは JavaScript の強力でとても柔軟な機能であり、コードの再利用やオブジェクトの結合を可能にします。

具体的には、プロトタイプは**継承**のバージョンに対応しています。継承とは、オブジェクト指向プログラミング言語の機能で、プログラマーが「システム内のあるオブジェクトは、他のオブジェクトのより特化したバージョンである」という考えを表現させることができます。

例えば、学校をモデル化する場合、教授と生徒がいるとします。これらはどちらも「人」であり、いくつかの特性（例えば、どちらも名前を持っている）を持っていますが、それぞれの例では追加する特性（教授は教える科目を持っている）があったり、同じ特性を異なる方法で実装したりするかもしれません。OOP システムでは、教授も学生も人から**継承している**と言います。

JavaScript で、`Professor` と `Student` のオブジェクトが `Person` プロトタイプを持つことができれば、共通のプロパティを継承することができる一方で、異なるプロパティを追加したり再定義したりしたりすることができることがおわかりいただけるでしょう。

次の記事では、オブジェクト指向プログラミング言語の他の主な機能とともに継承について説明し、JavaScript がどのように対応しているかを見ていくことにします。

まとめ
---

この記事では、プロトタイプオブジェクトチェーンによってオブジェクトが互いに機能を継承する方法、プロトタイププロパティとそれを使ってコンストラクタにメソッドを追加する方法など、JavaScript オブジェクトのプロトタイプを取り上げてきました。

次の記事では、オブジェクト指向プログラミングの基盤となる概念について見ていきます。

* 前のページ
* Overview: Objects
* 次のページ


JSON の操作 - ウェブ開発を学ぶ

JSON の操作
========

* 前のページ
* Overview: Objects
* 次のページ

JavaScript Object Notation (JSON) は、構造化データを表現するための標準のテキストベースの形式で、 JavaScript のオブジェクト構文に基づいています。ウェブアプリケーションでデータを転送する場合によく使われます（例えば、複数のデータをサーバーからクライアントへ送信して、ウェブページ上に表示する場合などで、その逆もあります）。頻繁に見かけるデータ形式ですので、この記事では JavaScript を使用して JSON を扱うのに必要なすべてのこと、例えば JSON を解釈してその中のデータにアクセスしたり、 JSON を作成したりする方法を説明します。

|  |  |
| --- | --- |
| 前提知識: | 基礎的なコンピューターの知識、HTML と CSS への基本的な理解、基礎的な JavaScript の理解（JavaScript の第一歩と JavaScript の構成要素を参照）とオブジェクト指向 JavaScript の基本（JavaScript オブジェクトの基本を参照）。 |
| 目標: | JSON に格納されたデータを扱う方法、JSON 文字列の生成方法について理解すること。 |

JSON とは何か
---------

JSON は JavaScript オブジェクトの構文に従ったテキストベースのデータ形式で、Douglas Crockford によって普及されました。JSON は JavaScript オブジェクトの構文に似ていますが、 JavaScript とは独立して扱われることがあり、多くのプログラミング言語環境には JSON を読み取ったり（解釈したり）生成したりする機能があります。

JSON は文字列として存在します。ですので、ネットワークを通してデータを転送したい場合に便利です。 JSON データへアクセスしたい場合は、JavaScript オブジェクトへ変換する必要があります。 JavaScript にはこれらを相互に変換できるメソッドを持った JSON というグローバルなオブジェクトがあるので、変換は難しくありません。

**メモ:** 文字列をネイティブオブジェクトへ変換することは「デシリアライズ」 (*deserialization*) と呼ばれており、ネイティブオブジェクトをネットワークを通して転送できように文字列へ変換することは「シリアライズ」 (*serialization*) と呼ばれています。

JSON 文字列はそれ自身をファイルとして格納することもできます。 `.json` という拡張子の付いたただのテキストファイルで、 MIME タイプは `application/json` です。

### JSON の構造

上で説明したように、JSON は JavaScript オブジェクトにとても似ている形式の文字列です。JSON では通常の JavaScript オブジェクトと同様な基本データ型（文字列、数値、配列、論理型やその他のリテラル型）を使うことができます。これにより、以下のように階層的にデータを構成することができます。

```json
{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
      "powers": [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name": "Eternal Flame",
      "age": 1000000,
      "secretIdentity": "Unknown",
      "powers": [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}
```

この文字列を JavaScript プログラムへ読み込むと（例えば、変数 `superHeroes` へ代入すると）と、 JavaScript オブジェクトの基本の記事で見たのと同様に、ドットや角括弧を使ってデータへアクセスすることができます。例えば次のようになります。

```js
superHeroes.homeTown;
superHeroes["active"];
```

さらに深い階層のデータへアクセスする場合は、単純にプロパティ名や配列のインデックスを連結します。例えば、メンバーリスト中 2 番目のヒーローの 3 番目の能力を参照する場合は、以下のようにします。

```js
superHeroes["members"][1]["powers"][2];
```

1. まず、変数名 `superHeroes` を指定します。
2. その中の `members` プロパティへアクセスしたいので、 `["members"]` と指定します。
3. `members` にはオブジェクトの配列が格納されています. ここでは、配列内の 2 番目のオブジェクトへアクセスするので、 `[1]` を指定します。
4. そのオブジェクト内で、 `powers` プロパティへアクセスするため, `["powers"]` と指定します。
5. `powers` プロパティは選択したヒーローの能力を含んだ配列となっており、その中の 3 番目が欲しいので、 `[2]` と記述します。

**メモ:** 上記の JSON は JSONTest.html で参照することができます（ページ内のソースコードを参照してください）。ページを読み込んで見て、ブラウザーのコンソールで変数内のデータにアクセスしてみてください。

JSON の配列
--------

上記で、 JSON テキストは基本的に文字列に入った JavaScript オブジェクトのように見えることを説明しました。配列を JSON との間で変換することもできます。例えば、次のものも有効な JSON です。

```json
[
  {
    "name": "Molecule Man",
    "age": 29,
    "secretIdentity": "Dan Jukes",
    "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
  },
  {
    "name": "Madame Uppercut",
    "age": 39,
    "secretIdentity": "Jane Wilson",
    "powers": [
      "Million tonne punch",
      "Damage resistance",
      "Superhuman reflexes"
    ]
  }
]
```

これも有効な JSON であり、解釈したデータには配列のインデックスを指定するだけです。例えば、`[0]["powers"][0]`のように表記できます。

### その他の注意点

* JSON は指定されたデータ形式の純粋な文字列です。プロパティのみを含むことができ、メソッドを含むことはできません。
* JSON では文字列とプロパティ名を二重引用符で括る必要があります。単一引用符は、JSON 文字列全体を囲む以外では無効です。
* カンマやコロンが 1 つ抜けるだけでも JSON ファイルは無効になり、動作しません。利用しようとしているデータを注意して確認してください（プログラムに問題がない限り、コンピューターが生成した JSON の方が、エラーが含まれる可能性が低くなります）。 JSONLint のようなアプリケーションを使って妥当性を検証をすることもできます。
* JSONは、配列やオブジェクトだけでなく、 JSON 内部に入れることができるあらゆるデータ型のデータだけでも有効なものになります。つまり、例えば、単一の文字列や数値も有効な JSON となります。
* JavaScript コードではプロパティを引用符で括らなくても構いませんが、 JSON では、引用符でくくった文字列だけがプロパティとして扱われます。
アクティブラーニング: JSON の例を操作してみる
--------------------------

それでは、ウェブサイト上でどのように JSON 形式のデータを使うことができるか例を通して見てみましょう。

### はじめに

まず、 heroes.html と style.css のコピーをローカルに作成してください。後者は例題ページをスタイリングするための CSS であり、前者は簡単な HTML です。加えて、`<script>` 要素で、この演習で書くJavaScriptコードを格納します。

```html
<header></header>

<section></section>

<script></script>
```

JSON データは GitHub の https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json で利用できます。

この JSON をスクリプトに読み込んで、DOM 操作を使って次のように表示することにします。

![（おしゃれなフォントで）"Super hero squad" と題され、 "Hometown: Metro City // Formed: 2016" と副題が付けられた文書の画像。見出しの下記 3 列には、それぞれ "Molecule Man", "Madame Uppercut", "Eternal Flame" というタイトルが付けられています。それぞれの列には、ヒーローの秘密の正体名、年齢、スーパーパワーが掲載されています。](/ja/docs/Learn/JavaScript/Objects/JSON/json-superheroes.png)

### 最上位の関数

最上位の関数はこんな感じです。

```js
async function populate() {
  const requestURL =
    "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
  const request = new Request(requestURL);

  const response = await fetch(request);
  const superHeroes = await response.json();

  populateHeader(superHeroes);
  populateHeroes(superHeroes);
}
```

 JSON を取得するには、フェッチという API を使用しています。
 この API では、JavaScript を介してサーバーからリソースを取得するためのネットワークリクエストを行うことができます（画像、テキスト、JSON、HTML スニペットなど）。つまり、ページ全体を再読み込みしなくても、コンテンツの小さなセクションを更新できるのです。

この関数では、最初の 4 つの行でフェッチ API を使用して、サーバーから JSON を取得しています。

* GitHub の URL を格納するために、`requestURL` という変数を宣言します。
* URL を使用して新しい `Request` オブジェクトを初期化します。
* `fetch()` 関数を使用してネットワーク要求を行い、`Response` オブジェクトを返します。
* レスポンスオブジェクトの `json()` 関数を使用して、レスポンスを JSON で取得します。

**メモ:** `fetch()` API は**非同期**です。非同期関数については次のモジュールでたくさん学びますが、今は、フェッチ API を使用する関数名の前にキーワード `async`、あらゆる非同期関数への呼び出し前にキーワード `await` が必要だということだけ言っておきます。

すべて完了すると、`superHeroes` 変数に JSON を基にした JavaScript オブジェクトが格納されます。最初のオブジェクトは `<header>` を正しいデータで満たし、2 つ目はチームの各ヒーローの情報カードを作成し、それを `<section>` に挿入しています。

### ヘッダーへの値の設定

ここまでで、JSON の取得と JavaScript オブジェクトへの変換ができました、先ほどの 2 つの関数を実装して使ってみましょう。まずはじめに、以下のコードをこれまでのコードの下に追加してください。

```js
function populateHeader(obj) {
  const header = document.querySelector("header");
  const myH1 = document.createElement("h1");
  myH1.textContent = obj.squadName;
  header.appendChild(myH1);

  const myPara = document.createElement("p");
  myPara.textContent = `Hometown: ${obj.homeTown} // Formed: ${obj.formed}`;
  header.appendChild(myPara);
}
```

まず、h1 要素を `createElement()` で生成し、その `textContent` プロパティにそのオブジェクトの `squadName` プロパティを設定し、そしてそれを `appendChild()` で header に追加します。そして、段落についても同様に、要素を生成し、内容のテキストを設定し、 header に追加します。唯一の違いは、そのテキストがオブジェクトの `homeTown` と `formed` プロパティの両方を格納したテンプレートリテラルに設定されることです。

### ヒーロー情報カードの作成

次に、以下の関数をコードの下へ追加してください。この関数はスーパーヒーローカードの作成と画面表示を行います。

```js
function populateHeroes(obj) {
  const section = document.querySelector("section");
  const heroes = obj.members;

  for (const hero of heroes) {
    const myArticle = document.createElement("article");
    const myH2 = document.createElement("h2");
    const myPara1 = document.createElement("p");
    const myPara2 = document.createElement("p");
    const myPara3 = document.createElement("p");
    const myList = document.createElement("ul");

    myH2.textContent = hero.name;
    myPara1.textContent = `Secret identity: ${hero.secretIdentity}`;
    myPara2.textContent = `Age: ${hero.age}`;
    myPara3.textContent = "Superpowers:";

    const superPowers = hero.powers;
    for (const power of superPowers) {
      const listItem = document.createElement("li");
      listItem.textContent = power;
      myList.appendChild(listItem);
    }

    myArticle.appendChild(myH2);
    myArticle.appendChild(myPara1);
    myArticle.appendChild(myPara2);
    myArticle.appendChild(myPara3);
    myArticle.appendChild(myList);

    section.appendChild(myArticle);
  }
}
```

始めに、JavaScript オブジェクトの `members` プロパティを新しい変数に保存します。この配列には複数のオブジェクトがあり、それぞれにヒーローについての情報が入ります。

次に、for...of ループを使って配列のそれぞれのオブジェクトを反復処理します。それぞれの次のようなことを行います。

1. 新しい要素をいくつか作成します。`<article>` 1 つ、 `<h2>` 1 つ、 `<p>` 3 つ、`<ul>` 1 つです。
2. `<h2>` の中身を現在のヒーローの名前 (`name`) にします。
3. 3 つの段落の中身を、それぞれの `secretIdentity`、 `age`、リストにある情報を紹介していくために「超能力 ("Superpowers:")」で始まる行とします。
4. `powers` プロパティを `superPowers` という新しい定数に保存します。この定数は今のヒーローの超能力のリストを持つ配列です。
5. 別の `for` ループを使用して、今のヒーローの超能力を反復処理します。それぞれに対して `<li>` 要素を作成し、中に超能力を入れ、 `listItem` に `<ul>` 要素（`myList`）を `appendChild()` で追加します。
6. 最後に、 `<h2>`、`<p>`、`<ul>` を `<article>` (`myArticle`) の中に追加してから、その `<article>` を `<section>` の中に追加します。これらを追加する順序は重要で、これが HTML の中で表示される順序になります。

**メモ:** 試してみるための例が上手く取得できなかった場合は、 heroes-finished.html ソースコードを参照してみてください（こちらでライブ実行もできます）。

**メモ:** もし、 JavaScript オブジェクトへのアクセスに使用しているドット/ブラケット記法がよく分からない場合は、 superheroes.json を別のタブやテキストエディターで開き、それを参照しながら JavaScript を読んでみるとよいでしょう。また、ドットやブラケット記法の詳細については、 JavaScript オブジェクトの基本の記事を見返してみてください。

### 最上位の関数の呼び出し

最後に、最上位の `populate()` 関数を呼び出す必要があります。

```js
populate();
```

オブジェクトとテキスト間の変換
---------------

上記の例では、`response.json()` を使用してネットワークレスポンスを直接 JavaScript オブジェクトに変換しているので、JavaScript オブジェクトへのアクセスはシンプルでした。

しかし、時にはそれほど幸運ではないこともあります。生の JSON 文字列を受け取り、それを自分自身でオブジェクトに変換する必要がある場合もあります。また、 JavaScript のオブジェクトをネットワーク経由で送信したい場合、送信前に JSON （文字列）に変換する必要があります。幸い、この 2 つの問題はウェブ開発ではよくあることなので、ブラウザーでは組み込みの JSON オブジェクトが利用でき、それには以下の 2 つのメソッドが備わっています。

* `parse()`: JSON 文字列を引数に取り、それに対する JavaScript オブジェクトを返します。
* `stringify()`: オブジェクトを引数に取り、等価な JSON 文字列を返します。

前者の動作例が heroes-finished-json-parse.html にあります（ソース を見て下さい）。ここでは以前に作成した例とまったく同じことをしていますが、次の部分が異なります。

* レスポンスの `text()` メソッドを呼び出すことで、JSON ではなくテキストとしてレスポンスを取得する
* 次に、`parse()` を使用して、テキストを JavaScript オブジェクトに変換する

コードの重要な部分は以下の通りです。

```js
async function populate() {
  const requestURL =
    "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
  const request = new Request(requestURL);

  const response = await fetch(request);
  const superHeroesText = await response.text();

  const superHeroes = JSON.parse(superHeroesText);
  populateHeader(superHeroes);
  populateHeroes(superHeroes);
}
```

ご想像の通り、 `stringify()` はまったく反対の向きに動作します。次のコードをブラウザーの JavaScript コンソールに一つずつ打ち込んでいって、実際に動かしてみて下さい。

```js
let myObj = { name: "Chris", age: 38 };
myObj;
let myString = JSON.stringify(myObj);
myString;
```

ここでは、 JavaScript オブジェクトを作成してその中身を確認しています。次に `stringify()` を使って JSON 文字列に変換し、返値を新しい変数に保存し、その値も確認しています。

スキルをテストしてみましょう
--------------

この記事はここまでですが、最重要事項を覚えていますか？先に進む前に、これが身に付いているかどうかを確認するためのテストがいくつかあります。スキルテスト: JSONを参照してください。

まとめ
---

この記事では、プログラム内で、JSON を生成する、JSON を解釈する、JSON データを参照するなど、JSON を扱う方法について簡単に説明しました。次の記事では、オブジェクト指向 JavaScript について見ていくことにします。

関連情報
----

* JSON リファレンス
* フェッチ API の概要
* フェッチの使用
* HTTP リクエストメソッド
* ECMA のオフィシャル JSON ウェブサイト
* 前のページ
* Overview: Objects
* 次のページ


JavaScript のクラス - ウェブ開発を学ぶ

JavaScript のクラス
===============

* 前のページ
* Overview: Objects
* 次のページ

前回の記事で、オブジェクト指向プログラミング (OOP) の基本的な概念を紹介し、OOP の原則を用いて学校の教授と生徒をモデル化した例を説明しました。

また、このようなモデルを実装するためにプロトタイプやコンストラクターを使用できることや、より古典的なOOP の概念に近い形で、 JavaScript にも機能を提供することができることもお話ししました。

この記事では、これらの機能について説明していきます。ここで記述する機能は、オブジェクトを結合する新しい方法ではないことに留意する必要があります。プロトタイプチェーンを簡単に設定するための方法なのです。

|  |  |
| --- | --- |
| 前提知識: | JavaScript 関数の理解、基本的な HTML と CSS 理解、JavaScript の基礎知識（JavaScript の第一歩や JavaScript の構成要素を参照）、OOJS の基礎（オブジェクトの基本、オブジェクトのプロトタイプ、オブジェクト指向プログラミングを参照）。 |
| 目標: | 「古典的な」オブジェクト指向プログラムを実装するために、JavaScript が提供する機能をどのように使用するかを理解すること。 |

クラスとコンストラクター
------------

クラスは `class` キーワードを使用して宣言することができます。ここでは、前回記事で紹介した `Person` のクラス宣言を紹介します。

```js
class Person {
  name;

  constructor(name) {
    this.name = name;
  }

  introduceSelf() {
    console.log(`Hi! I'm ${this.name}`);
  }
}
```

これは `Person` というクラスを次のように宣言しています。

* `name` プロパティ。
* 新しいオブジェクトの `name` プロパティを初期化するために使用する `name` 引数を受け取るコンストラクター。
* `this` を用いてオブジェクトのプロパティを参照することができる `introduceSelf()` メソッド。

`name;` 宣言はオプションです。除外しても、コンストラクターの `this.name = name;` という行は、初期化する前に `name` プロパティを作成します。しかし、クラス宣言の中でプロパティを明示的に記載しておくと、コードを読む人がどのプロパティがこのクラスの一部であるかを容易に知ることができるかもしれません。

また、プロパティを宣言するときに、`name = '';` のような行で、プロパティを既定値に初期化することも可能です。

コンストラクターは `constructor` キーワードを使って定義します。クラス定義外のコンストラクターと同じように、次のようになります。

* 新しいオブジェクトを生成する
* 新しいオブジェクトに `this` を結びつけ、コンストラクターのコードで `this` を参照することができるようにする
* コンストラクターでコードを実行する
* 新しいオブジェクトを返す

上記のクラス宣言コードを指定された場合、次のように新しい `Person` インスタンスを作成して使用することができます。

```js
const giles = new Person("Giles");

giles.introduceSelf(); // Hi! I'm Giles
```

この例では、クラスの名前 `Person` を用いてコンストラクターを呼び出していることに注意してください。

### コンストラクターの省略

特別な初期化をする必要がない場合は、コンストラクターを省略することができ、既定のコンストラクターが生成されます。

```js
class Animal {
  sleep() {
    console.log("zzzzzzz");
  }
}

const spot = new Animal();

spot.sleep(); // 'zzzzzzz'
```

継承
--

上記の `Person` クラスを指定されたので、`Professor` サブクラスを定義してみましょう。

```js
class Professor extends Person {
  teaches;

  constructor(name, teaches) {
    super(name);
    this.teaches = teaches;
  }

  introduceSelf() {
    console.log(
      `My name is ${this.name}, and I will be your ${this.teaches} professor.`,
    );
  }

  grade(paper) {
    const grade = Math.floor(Math.random() \* (5 - 1) + 1);
    console.log(grade);
  }
}
```

このクラスが他のクラスを継承していることを表すために `extends` キーワードを使用しています。

`Professor` クラスは新しいプロパティ `teaches` を追加しているので、それを宣言しています。

新しい `Professor` が作成されたときに `teaches` を設定したいので、`name` と `teaches` を引数に取るコンストラクターを定義します。このコンストラクターが最初に行うことは、`super()` を使ってスーパークラスのコンストラクターを呼び出すことで、`name` の引数を渡す。スーパークラスのコンストラクターは `name` を設定する処理を行います。その後、`Professor` コンストラクターは、`teaches` プロパティを設定します。

**メモ:** サブクラスが自分自身で初期化を行う場合は、最初に `super()` を用いてスーパークラスのコンストラクターを呼び出し、スーパークラスのコンストラクターが期待する引数をすべて渡す**必要があります**。

また、スーパークラスの `introduceSelf()` メソッドをオーバーライドし、新しいメソッド `grade()` を追加して、論文を採点するようにしました（この教授はとても優秀ではなく、論文にランダムに成績を割り当てるだけです）。

この宣言により、これで教授を作成し、使用することができるようになりました。

```js
const walsh = new Professor("Walsh", "Psychology");
walsh.introduceSelf(); // 'My name is Walsh, and I will be your Psychology professor'

walsh.grade("my paper"); // some random grade
```

カプセル化
-----

最後に、JavaScript でカプセル化を実装するために、どのようにすればよいかを見てみましょう。前の記事では、`Student` の `year` プロパティを非公開にすることで、`Student` クラスを使用するコードを壊すことなく、アーチェリークラスに関するルールを変更したいことを説明しました。

ここでは、それを実現する `Student` クラスの宣言を示します。

```js
class Student extends Person {
  #year;

  constructor(name, year) {
    super(name);
    this.#year = year;
  }

  introduceSelf() {
    console.log(`Hi! I'm ${this.name}, and I'm in year ${this.#year}.`);
  }

  canStudyArchery() {
    return this.#year > 1;
  }
}
```

このクラス宣言では、`#year` は プライベートデータプロパティです。`Student` オブジェクトを作成し、内部で `#year` を使用することができますが、オブジェクトの外のコードが `#year` にアクセスしようとすると、ブラウザはエラーを報告します。

```js
const summers = new Student("Summers", 2);

summers.introduceSelf(); // Hi! I'm Summers, and I'm in year 2.
summers.canStudyArchery(); // true

summers.#year; // SyntaxError
```

プライベートデータプロパティはクラス宣言で宣言する必要があり、その名前は `#` で始まります。

### プライベートメソッド

プライベートデータプロパティと同様に、プライベートメソッドも持つことができます。プライベートデータプロパティと同様に、その名前は `#` で始まり、オブジェクト自身のメソッドによってのみ呼び出すことができます。

```js
class Example {
  somePublicMethod() {
    this.#somePrivateMethod();
  }

  #somePrivateMethod() {
    console.log("You called me?");
  }
}

const myExample = new Example();

myExample.somePublicMethod(); // 'You called me?'

myExample.#somePrivateMethod(); // SyntaxError
```

スキルをテストしましょう
------------

この記事の終わりまで来ましたが、最も重要な情報を覚えていますか？次に行く前に、この情報を覚えているかどうかを確認するためのテストがいくつかあります - Test your skills: Object-oriented JavaScript を参照してください。

まとめ
---

 この記事では、オブジェクト指向のプログラムを書くために JavaScript で利用できる主なツールについて説明しました。ここですべてを網羅したわけではありませんが、始めるには十分でしょう。この記事で紹介したクラスの記事は、さらに詳しく学ぶには良い場所です。

* 前のページ
* Overview: Objects
* 次のページ


バウンスボールのデモに機能を追加する - ウェブ開発を学ぶ

バウンスボールのデモに機能を追加する
==================

* 前のページ
* Overview: Objects

この評価では、前の記事のバウンスボールのデモを出発点として用い、いくつかの面白い機能を新たに追加してもらいます。

|  |  |
| --- | --- |
| 前提条件: | この評価を試みる前に、このモジュールのすべての記事を学習済みであること。 |
| 目標: | JavaScript オブジェクトとオブジェクト指向のインスタンス生成を理解しているかテストする。 |

出発点
---

この評価をスタートするためには、ローカル PC の新しいディレクトリーに最新記事から index-finished.html、style.css、main-finshed.js をコピーします。

または、評価のために、 JSBin や Glitch を使うことができます。これらのオンラインエディターに HTML、CSS や JavaScript を貼り付けることができます。もしあなたが使用しているオンラインエディターが、別々の JavaScript/CSS のパネルを持っていない場合は、HTML内の `<script>`/`<style>` 要素を使って、インラインで書くことができます。

**メモ:** 行き詰まった場合は、サポートを依頼してください。このページの下部にある評価とさらなる支援の節を参照してください。

ヒントと tips
---------

始める前にいくつかの助言です。

* この評価はかなり難しいです。コーディングを始める前に評価全体を読み、各ステップをゆっくりと注意深く行ってください。
* それぞれのステージを作業した後のデモを、別々のコピーとして保管しておけば、後で困ったときに参照することができます。
プロジェクト概要
--------

このバウンスボールのデモは面白いですが、ここではもう少しインタラクティブにするため、バウンスボールを捕まえたら食べてしまう、ユーザー制御された邪悪な円を追加します。また、バウンスボールや邪悪な円が継承できる一般的な `Shape()` オブジェクトを作ることで、あなたのオブジェクト構築スキルも試してみましょう。最後に、残ったボールが数えられるスコアカウンターも追加してみましょう。

次のスクリーンショットでは、完成したプログラムがどのように見えるかのイメージを掴めるでしょう。

![バウンシングボールのデモページのスクリーンショット。色のついたボールの他に白抜きの円が見え、見出しの下に "Ball count:23" と表示されている。](/ja/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features/bouncing-evil-circle.png)

もっとアイディアを得たい場合は、完成デモを見てみましょう。（ソースコードをチラ見しないように！）

完成までの手順
-------

次の節では、必要な操作について説明します。

### 新しいオブジェクトを作る

まず最初に、新しい `Shape` クラスを作成します。これはコンストラクターしかありません。 `Shape` コンストラクターは `Ball()` コンストラクターと同じように `x`, `y`, `velX`, `velY` プロパティを定義しますが、 `color` と `size` プロパティは定義しないでください。

`Ball` クラスは `extends` を使用して `Shape` から派生させる必要があります。 `Ball` のコンストラクターは以下のようになります。

* 引数として、 `x`, `y`, `velX`, `velY`, `size`, `color` を受け取ります。
* `super()` を使用して `Shape` コンストラクタを呼び出し、 `x`、`y`、`velX`、`velY` の各引数を渡します。
* 与えられたパラメータから `color` と `size` のプロパティを初期化します。

`Ball` コンストラクターは `exists` という新しいプロパティを定義する必要があります。これは、ボールがプログラム内に存在するかどうか（悪のサークルに食べられていないかどうか）を追跡するために使用されます。これは論理値 (`true`/`false`) で、コンストラクターの中で `true` に初期化する必要があります。

`Ball` クラスの `collisionDetect()` メソッドは小さな更新が必要です。ボールは `exists` プロパティが `true` のときだけ衝突判定を行う必要があります。そこで、既存の `collisionDetect()` コードを以下のコードに置き換えてください。

```js
collisionDetect() {
  for (const ball of balls) {
    if (!(this === ball) && ball.exists) {
      const dx = this.x - ball.x;
      const dy = this.y - ball.y;
      const distance = Math.sqrt(dx \* dx + dy \* dy);

      if (distance < this.size + ball.size) {
        ball.color = this.color = randomRGB();
      }
    }
  }
}
```

上述したように、ボールが存在するかどうかをチェックするために、 `if` 条件で `ball.exists` を使用することが追加されただけです。

ボールの `draw()` と `update()` メソッドの定義は、以前と全く同じであるべきです。

この時点で、コードを再読み込みしてみましょう。再設計されたオブジェクトを使用して、以前と同じように動作するはずです。

### EvilCircle の定義

さあ、悪者 `EvilCircle()` の登場です。私たちのゲームに邪悪な円は 1 つしか登場しませんが、練習のためにあえて、`Shape()` から継承するコンストラクターを使用して定義します。後で、他のプレイヤーによって制御される円、あるいは、コンピューター制御の別の邪悪な円をいくつか加えたいと思うかもしれません。おそらく、あなたは単一の邪悪な円の世界を引き継いでいくつもりはないでしょうが、今回の評価のためにはこれで十分です。

`EvilCircle` クラスの定義を作成します。これは `Shape` を `extends` を使って継承する必要があります。

#### EvilCircle コンストラクター

`EvilCircle` のコンストラクターは以下のようなものです。

* 引数として `x`, `y` だけが渡されます。
* 引数 `x`, `y` を、スーパークラス `Shape` にハードコードした `velX`, `velY` 共に渡します。これを行うには、 `super(x, y, 20, 20);` のようなコードで行います。
* `color` を `white` に、 `size` を `10` に設定します。

最後に、コンストラクターは、ユーザーが画面上で悪の円を動かせるようにコードを設定する必要があります。

```js
window.addEventListener("keydown", (e) => {
  switch (e.key) {
    case "a":
      this.x -= this.velX;
      break;
    case "d":
      this.x += this.velX;
      break;
    case "w":
      this.y -= this.velY;
      break;
    case "s":
      this.y += this.velY;
      break;
  }
});
```

これは `keydown` イベントリスナーを `window` オブジェクトに追加し、キーが押されたときにイベントオブジェクトの `key` プロパティを参照し、どのキーが押されたかを確認するようにしたものです。もし、指定された 4 つのキーのうちの 1 つであれば、邪悪な円は左/右/上/下へと移動します。

### EvilCircle のメソッドの定義

`EvilCircle` には、以下に示す 3 つのメソッドがあります。

#### draw()

このメソッドは、`Ball()` の `draw()` メソッドと同じく、キャンバス上にオブジェクトインスタンスを描画するという目的を持ちます。とても良く似た動作をするので、`Ball` の `draw()` メソッドの定義をコピーすることから始めます。次に、以下の変更を行います。

* 邪悪な円は塗りつぶしせず、枠線（ストローク）だけを持たせたいと思います。そのために、`fillStyle` と `fill()` (en-US) を `strokeStyle` と `stroke()` にそれぞれ変更します。
* また、線を少し太くすれば、邪悪な円が少し分かりやすくなります。これは、 `lineWidth` (en-US) の値（3 で十分でしょう）を `beginPath()` 呼び出しの後のどこかで設定することで実現できます 。

#### checkBounds()

このメソッドは、 `Ball` の `update()` メソッドの最初の部分と同じ機能、すなわち、邪悪な円が画面の端から出そうになったら出ないようにする機能を持ちます。先ほどと同様に、`Ball` の `update()` の定義をほぼコピーするだけでできますが、いくつか変更する必要があります。

* 最後の 2 行を削除します。後で見られるように、別の方法で邪悪な円を動かすので、フレーム毎に邪悪な円の位置を自動的に更新する必要はありません。
* `if ()` 文の内部でそのテストが true を返す場合、`velX`/`velY` を更新したくありません。代わりに `x`/`y` の値を変更して、邪悪な円が画面内に少し跳ね返ってくるようにしたいのです。邪悪な円の `size` プロパティを（適切に）加えたり減じたりすることは理にかなっています。

#### collisionDetect()

このメソッドは `Ball` の `collisionDetect()`メソッドと非常によく似た方法で動作するので、そのコピーをこの新しいメソッドの基礎として使用することができます。しかし、いくつかの違いがあります。

* 外側の `if` 文では、反復処理中のボールが、チェックを行っているボールと同じであるかをチェックする必要はなくなりました。なぜなら、それは邪悪な円であって、ボールではないからです！ その代わりに、チェックされているボールが存在するかどうかを確認（どのプロパティでこれを行うことができるでしょうか？）するテストを行う必要があります。存在しなければ、それはすでに邪悪な円によって食べられているので、再度チェックする必要はありません。
* 内部の `if` 文では、衝突が検出されたときにオブジェクトの色を変更する必要がなくなりました。その代わりに、邪悪な円と衝突するボールをもう存在しないように設定します（どうやって実行すると思いますか？）。
### プログラムに邪悪な円を持ち込む

さて、邪悪な円を定義したので、実際にそれをシーンに表示させる必要があります。そのためには、 `loop()` 関数をいくつか変更する必要があります。

* まず、（必要な引数を指定して）新しい邪悪な円オブジェクトインスタンスを作成します。これは一度だけ実行すればよく、ループの繰り返し毎に行う必要はありません。
* すべてのボールをループして、ボールが存在する場合にのみ、それぞれの `draw()`、`update()`、`collisionDetect()` が呼び出されるようにします。
* ループの各繰り返しで、邪悪なボールのインスタンスの `draw()`、`checkBounds()`、および `collisionDetect()`メソッドを呼び出します。
### スコアカウンターの実装

スコアカウンターを実装するには、次の手順に従います。

1. HTML ファイルの h1 要素の直下に、"Ball count:" というテキストを含む `<p>` 要素を追加します。
2. CSS ファイルに、次のスタイルを追加します。

```css
p {
  position: absolute;
  margin: 0;
  top: 35px;
  right: 5px;
  color: #aaa;
}
```

3. JavaScript では、次の更新を行います。
    * 段落への参照を格納する変数を作成します。
    * 何らかの方法で画面上のボールの数をカウントしてください。
    * ボールをシーンに追加するたびにカウントを増加させ、更新されたボールの数を表示します。
    * 邪悪な円がボールを食べる（存在を消す）たびにカウントを減らし、更新されたボールの数を表示します。
評価とさらなる支援
---------

自分の作品を評価してほしい、行き詰っているので相談したい方は、次のようにしましょう。

1. 自分の作品を CodePen, jsFiddle や Glitch などのオンラインで共有できるエディターに入れます。
2. MDN Discourse フォーラムの Learning カテゴリーに、評価や支援を求める投稿を（英語で）書き込んでください。投稿には次のことを書いてください。
    * "Assessment wanted for Adding bouncing balls features" のような、説明的なタイトル。
    * すでに試したことの詳細と、私たちに何をしてほしいか（例: 行き詰まり、助けが必要な場合、または評価が必要な場合）。
    * 評価やヘルプが必要なサンプルへのリンクを、オンライン共有可能なエディター（上記のステップ 1 で述べたとおり）にて提供します。コードを見ることができなければ、コーディングの問題で誰かを助けることは非常に困難です。
    * 実際の課題または評価ページへのリンクにより、助けを求めている問題を見つけることができます。
* 前のページ
* Overview: Objects


スキルテスト: オブジェクト指向 JavaScript - ウェブ開発を学ぶ

スキルテスト: オブジェクト指向 JavaScript
===========================

このスキルテストの目的は、JavaScript でのクラスの記事を理解できたかどうかを評価することです。

**メモ:** 下記のインタラクティブエディターで解答を試すことができますが、コードをダウンロードして、CodePen, jsFiddle, Glitch などのオンラインツールを使用して作業すると便利です。

もし行き詰まった場合は、このページの下にある「評価とさらなる支援」(#評価とさらなる支援)の節を参照して、私たちに支援を要求してください。

**メモ:** 下記の例では、コードにエラーがある場合、ページ上の結果パネルに出力されるので、答え合わせをするのに役立ちます（ダウンロードした場合には、ブラウザーの JavaScript コンソールに出力されます）。

OOJS 1
------

このタスクでは、`Shape` クラスの定義から始めましょう。このクラスには `name`, `sides`, `sideLength` の 3 つのプロパティがあります。このクラスは、正方形や正三角形のように、すべての辺の長さが同じである図形のみをモデルとしています。

次のことをやってください。

* このクラスにコンストラクターを追加しましょう。コンストラクターは `name`, `sides`, `sideLength` プロパティを引数に取り、初期化します。
* このクラスに新しいメソッド `calcPerimeter()` を追加しましょう。このメソッドは、外周の長さ（図形の外縁の長さ）を計算し、その結果をコンソールにログ出力します。
* `Shape` クラスの新しいインスタンス `square` を作成しましょう。名前に `square`、 `sides` に `4`、 `sideLength` に `5` を指定しましょう。
* このインスタンスに対して `calcPerimeter()` メソッドを呼び出して、計算結果が期待通りにブラウザーコンソールにログ出力されるかどうかを確認しましょう。
* 新しい `Shape` のインスタンスとして `triangle` を作成しましょう。名前は `triangle`、`sides` は `3`、`sideLength` は `3` とします。
* triangle.calcPerimeter()`を呼び出して、問題なく動作することを確認しましょう。

下記のライブコードを更新して、完成例を再現してみてください。

自分自身でエディターやオンラインエディターで作業する場合は、この作業の開始時点のものをダウンロードしましょう。

OOJS 2
------

次に、`Shape`を継承した `Square` クラスを作成し、正方形の面積を計算する `calcArea()` メソッドを追加しましょう。また、`Square` オブジェクトインスタンスの `name` プロパティには自動的に `square` が設定され、`sides` プロパティには自動的に `4` が設定されるようにコンストラクターを設定しましょう。したがって、コンストラクターを呼び出す際には、`sideLength` プロパティだけを提供すればよいことになります。

適切なプロパティ値を持つ `Square` クラスのインスタンス `square` を作成し、その `calcPerimeter()` と `calcArea()` メソッドを呼び出して、問題なく動作することを示しましょう。

下記のライブコードを更新して、完成例を再現してみてください。

自分自身でエディターやオンラインエディターで作業する場合は、この作業の開始時点のものをダウンロードしましょう。

評価とさらなる支援
---------

これらの例は、上記のインタラクティブエディターで練習することができます。

自分の作品を評価してほしい、行き詰っているので相談したい方は、次のようにしましょう。

1. 自分の作品を CodePen, jsFiddle や Glitch などのオンラインで共有できるエディターに入れます。
2. MDN Discourse フォーラムの Learning カテゴリーに、評価や支援を求める投稿を（英語で）書き込んでください。投稿には次のことを書いてください。
    * "Assessment wanted for OOJS 1 skill test" のような、説明的なタイトル。
    * すでに試したことの詳細と、私たちに何をしてほしいか（例: 行き詰まり、助けが必要な場合、または評価が必要な場合）。
    * 評価やヘルプが必要なサンプルへのリンクを、オンライン共有可能なエディター（上記のステップ 1 で述べたとおり）にて提供します。コードを見ることができなければ、コーディングの問題で誰かを助けることは非常に困難です。
    * 実際の課題または評価ページへのリンクにより、助けを求めている問題を見つけることができます。


スキルテスト: JSON - ウェブ開発を学ぶ

スキルテスト: JSON
============

このスキルテストの目的は、JSON の操作の記事を理解できたかどうかを評価することです。

**メモ:** 下記のインタラクティブエディターで解答を試すことができますが、コードをダウンロードして、CodePen, jsFiddle, Glitch などのオンラインツールを使用して作業すると便利です。

もし行き詰まった場合は、このページの下にある「評価またはさらなる支援」(#評価またはさらなる支援)の節を参照して、私たちに支援を要求してください。

**メモ:** 下記の例では、コードにエラーがある場合、ページ上の結果パネルに出力されるので、答え合わせをするのに役立ちます（ダウンロードした場合には、ブラウザーの JavaScript コンソールに出力されます）。

JSON 1
------

この記事の唯一の課題は、JSON データにアクセスして、それをページ内で使用することに関するものです。いくつかの母猫とその子猫に関する JSON データが sample.json で提供されています。JSON は文字列としてページに読み込まれ、`displayCatInfo()` 関数の `catString` 引数で利用できるようになります。課題は、`displayCatInfo()` 関数の欠落部分を埋めて格納することです。

* 母猫 3 匹の名前をカンマで区切って `motherInfo` という変数に入れてください。
* `kittenInfo` 変数には、子猫の総数、およびオスとメスの数を格納してください。

そして、これらの変数の値が、段落の中で画面に表示されるようにします。

ヒントや質問をいくつか示します。

* JSON データは `displayCatInfo()` 関数の中でテキストとして提供されます。JSON から何かデータを取得する前に、JSON を解釈する必要があります。
* 外側のループを使用して猫をループ処理して、その名前を `motherInfo` 変数文字列に追加し、内側のループを使用してすべての子猫をループ処理して、すべての子猫/オス/メスの合計を加算し、その詳細を `kittenInfo` 変数の文字列に追加するとよいでしょう。
* 最後の母猫の名前の前に "and" を、その後にピリオドを置く必要があります。どうすれば、JSON に何匹の猫がいても、このような動作をさせることができるでしょうか。
* なぜ `para1.textContent = motherInfo;` と `para2.textContent = kittenInfo;` の行は `displayCatInfo()` 関数の中にあり、スクリプトの終わりにはないのでしょうか。これは、非同期コードと関係があります。

下記のライブコードを更新して、完成例を再現してみてください。

自分自身でエディターやオンラインエディターで作業する場合は、この作業の開始時点のものをダウンロードしましょう。

評価とさらなる支援
---------

これらの例は、上記のインタラクティブエディターで練習することができます。

自分の作品を評価してほしい、行き詰っているので相談したい方は、次のようにしましょう。

1. MDN Discourse フォーラムの Learning カテゴリーに、評価や支援を求める投稿を（英語で）書き込んでください。投稿には次のことを書いてください。
    * "Assessment wanted for JSON skill test" のような、説明的なタイトル。
    * すでに試したことの詳細と、私たちに何をしてほしいか（例: 行き詰まり、助けが必要な場合、または評価が必要な場合）。
    * コード。
    * 実際の課題または評価ページへのリンクにより、助けを求めている問題を見つけることができます。


スキルテスト: オブジェクトの基本 - ウェブ開発を学ぶ

スキルテスト: オブジェクトの基本
=================

このスキルテストの目的は、JavaScript オブジェクトの基本の理解度をテストすることです。

**メモ:** 以下のインタラクティブなエディターでソリューションを試すこともできますが、コードをダウンロードし、CodePen, jsFiddleやGlitchのようなオンラインツールを使用してタスクを実行すると役立つ場合があります。

行き詰まった場合は、助けを求めてください — このページの下部にある評価またはさらなる支援セクションを参照してください。

**メモ:** 以下の例では、コードにエラーがある場合、ページの結果パネルに出力され、答えを見つけ出すのに役立ちます（ダウンロード可能なバージョンの場合は、ブラウザーの JavaScript コンソールに）

オブジェクトの基本 1
-----------

このタスクでは、オブジェクトリテラルが与えられます。あなたのタスクは下記です。

* `catName`変数に、**角括弧記法**を用いて、`name`プロパティの値を保存する
* **ドット記法**を用いて、`greeting()`メソッドを使う
* `color`プロパティを`black`に変更する

以下のライブコードを更新して、完成した例を再現してみてください。

**メモ:** このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

オブジェクトの基本 2
-----------

次のタスクでは、お気に入りのバンドの 1 つを表す、自分だけのオブジェクトリテラルを作成してみましょう。必要な要素は次のとおりです。

* `name`: バンドの名前を表す文字列
* `nationality`: バンドの出身国を表す文字列
* `genre`: バンドが演奏する音楽の種類
* `members`: バンドのメンバー数を表す数字
* `formed`: バンドが結成した年を表す数字
* `split`: バンドが解散した年を表す数字、まだ活動している場合は`false`
* `albums`: そのバンドによってリリースされたアルバムを表す配列。それぞれの配列の要素は、下記の要素を含んだオブジェクトであること
    + `name`: アルバムの名前を表す文字列
    + `released`: リリースされた年を表す数字

`albums` 配列には、少なくとも 2 つのアルバムを含めること。

これが終わったら、変数`bandInfo`に、名前、国籍、活動年数、スタイル、最初のアルバムのタイトルと発売日などの少しの詳細を書き込みます。

以下のライブコードを更新して、完成した例を再現してみてください。

**メモ:** このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

オブジェクトの基本 3
-----------

最後に、「オブジェクトの基本」のまとめとして、タスク＃1 の`cat`オブジェクトリテラルに戻りましょう。 「`Hello, said Bertie the Cymric.`」と記録されるように、`greeting（）`メソッドを書き直してください。 ブラウザーの DevTools のコンソールにアクセスしますが、名前や品種に関係なく、同じ構造のすべての`cat`オブジェクトで機能します。

完了したら、`cat2`という独自のオブジェクトを作成します。このオブジェクトは、同じ構造、まったく同じ`greeting（）`メソッドを持ちますが、名前、品種、色が異なります。

両方の`greeting（）`メソッドを呼び出して、適切なあいさつ（greeting）がコンソールに記録されることを確認します。

コードはあまりDRYではありません（それぞれは 1 回だけ定義すること）—たとえば、同じメソッドを 2 回定義しています。 どうすればもっと DRY にすることができますか？ よくわからない場合でも、心配しないでください。これは、シリーズの今後の記事で取り上げる予定です。

以下のライブコードを更新して、完成した例を再現してみてください。

**メモ:** このタスクの開始点をダウンロードして、お好きなエディターまたはオンライン・エディターで作業してください。

まとめとヘルプ
-------

自分のコードの評価が欲しい、または行き詰まって助けを求めたい場合：

1. CodePen、jsFiddle、Glitch などのオンライン共有可能なエディターで作業をします。コードを自分で作成することも、上記のセクションでリンクされているスターティングポイントファイルを使用することもできます。
2. MDNDiscourse フォーラムの学習カテゴリで評価や支援を求める投稿を書いてください。投稿には次のものを含める必要があります。

* 「オブジェクトの基本 1 の スキルテスト を行ったので評価して欲しい」などの説明的なタイトル。
* あなたがすでに試したことの詳細、そしてあなたが私たちに何をしてほしいか、例えば行き詰まって助けが必要な場合、または評価が必要な場合。
* オンラインの共有可能なエディターで、評価したい、または支援が必要な例へのリンク（上記のステップ 1 で説明）。これは入門するのに良い習慣です—あなたが彼らのコードを見ることができないならば、コーディング問題で誰かを助けることは非常に難しいです。
* 実際のタスクまたは評価ページへのリンク。サポートが必要な質問を見つけることができます。


オブジェクト指向プログラミング - ウェブ開発を学ぶ

オブジェクト指向プログラミング
===============

* 前のページ
* Overview: Objects
* 次のページ

オブジェクト指向プログラミング (OOP) は、Java や C++ をはじめとする多くのプログラミング言語の基本となるプログラミングパラダイムです。この記事では、OOP の基本的な概念について説明します。主に**クラスとインスタンス**、**継承**、**カプセル化**の 3 つの概念を説明します。これは、特に JavaScript を参照することなくこれらの概念を記述することになるので、すべての例は擬似コードで示されます。

**メモ:** 正確には、ここで記述されている機能は、**クラスベース**または「古典的」OOP と呼ばれる OOP の特定のスタイルのものです。人々が OOP について語るとき、一般的にはこの種類を意味します。

その後、JavaScript で、コンストラクターとプロトタイプチェーンがこれらの OOP の概念にどのように関連しているか、またどのように異なるかを見ていきます。次の記事では、オブジェクト指向のプログラムを実装するために、JavaScript の追加機能を紹介します。

|  |  |
| --- | --- |
| 前提知識: | JavaScript 関数の理解、JavaScript の基礎知識（JavaScript の第一歩と JavaScript の構成要素を参照）、OOJS の基礎（オブジェクトの基本、オブジェクトのプロトタイプを参照）。 |
| 目標: | クラスベースのオブジェクト指向プログラミングの基本的な概念を理解すること。 |

オブジェクト指向プログラミングは、システムをオブジェクトの集合としてモデル化することであり、各オブジェクトはシステムの具体的な側面を表します。オブジェクトには、関数（またはメソッド）とデータの両方が格納されています。オブジェクトは、使用したい他のコードに公開インターフェイスを提供しますが、自分自身でプライベートな内部状態を維持します。システムの他の部分は、オブジェクトの内部で何が起こっているかを気にする必要はありません。

クラスとインスタンス
----------

OOP でオブジェクトの観点から問題をモデル化する場合、システムにあるべきオブジェクトの種類を表す抽象的な定義が作成されます。例えば、学校をモデル化する場合、教授を表すオブジェクトを持つことができるかもしれません。すべての教授には、名前と教科という共通プロパティがあります。また、すべての教授ができることは決まっています。例えば、すべて論文の採点ができ、例えば、年度始めには学生に自己紹介をすることができます。

つまり、`Professor` は我々のシステムにおける**クラス**となり得るのです。クラスの定義には、すべての教授が持つデータとメソッドが掲載されています。

擬似コードでは、`Professor` クラスは次のように書くことができます。
```

class Professor
    properties
        name
        teaches
    methods
        grade(paper)
        introduceSelf()
```

これは、`Professor` クラスを次のように定義しています。

* 2 つのデータプロパティ: `name` と `teaches`
* 2 つのメソッド: `grade()` は論文の採点、`introduceSelf()` は自己紹介を行う。

クラスは自分自身で何かをするわけではなく、その種類の具体的なオブジェクトを作成するためのテンプレートのようなものです。作成する具体的な教授たちは、それぞれ `Professor` クラスの**インスタンス**と呼ばれます。インスタンスを作成する処理は、**コンストラクター**と呼ばれる特別な関数によって実行されます。コンストラクターには、新しいインスタンスで初期化したい内部状態を表す値を渡します。

一般に、コンストラクターはクラス定義の一部として書き出され、通常はクラスそのものと同じ名前を持っています。
```

class Professor
    properties
        name
        teaches
    constructor
        Professor(name, teaches)
    methods
        grade(paper)
        introduceSelf()
```

このコンストラクターは引数を2つ取るので、新しい具体的な教授を作成するときに `name` と `teaches` のプロパティを初期化することができます。

これでコンストラクターがあるので、いくつかの教授を作成することができます。プログラミング言語では、しばしば `new` キーワードを使用して、コンストラクターを呼び出すことを指示します。

```js
walsh = new Professor("Walsh", "Psychology");
lillian = new Professor("Lillian", "Poetry");

walsh.teaches; // 'Psychology'
walsh.introduceSelf(); // 'My name is Professor Walsh and I will be your Psychology professor.'

lillian.teaches; // 'Poetry'
lillian.introduceSelf(); // 'My name is Professor Lillian and I will be your Poetry professor.'
```

これは 2 つのオブジェクトを作成します。どちらも `Professor` クラスのインスタンスです。

継承
--

学校で、学生も表したいとします。教授とは異なり、学生は論文を採点することができず、特定の科目を教えることもなく、特定の学年に所属することもありません。

しかし、学生は名前を持ち、自己紹介をすることもできるので、学生クラスの定義を次のように書くことにします。
```

class Student
    properties
        name
        year
    constructor
        Student(name, year)
    methods
        introduceSelf()
```

学生と教授が何らかのプロパティを共有しているという事実、より正確には、あるレベルでは、それらは *同じ種類のもの* であるという事実を表すことができれば便利でしょう。これを実現するのが、**継承**です。

まず、学生も教授も人間であり、人間には名前があり、自己紹介をしたいということを観察することから始めます。このモデルは新しいクラス `Person` を定義することで実現でき、そこで人に共通するプロパティをすべて定義します。そして、`Professor` と `Student` は `Person` から**派生**することができ、それぞれのプロパティを追加することができます。
```

class Person
    properties
        name
    constructor
        Person(name)
    methods
        introduceSelf()

class Professor : extends Person
    properties
        teaches
    constructor
        Professor(name, teaches)
    methods
        grade(paper)
        introduceSelf()

class Student : extends Person
    properties
        year
    constructor
        Student(name, year)
    methods
        introduceSelf()
```

この場合、`Person` は `Professor` と `Student` の両方の**スーパークラス**または**親クラス**であると言うことになります。逆に、`Professor` と `Student` は `Person` の**サブクラス**または**子クラス**であると言えます。

この 3 つのクラスすべてで `introduceSelf()` が定義されていることにお気づきでしょうか。この理由は、すべての人が自己紹介をしたいが、その方法は異なるからです。

```js
walsh = new Professor("Walsh", "Psychology");
walsh.introduceSelf(); // 'My name is Professor Walsh and I will be your Psychology professor.'

summers = new Student("Summers", 1);
summers.introduceSelf(); // 'My name is Summers and I'm in the first year.'
```

学生でも教授でもない人のために、`introduceSelf()` の既定の実装を置いた方が良いかもしれません。

```js
pratt = new Person("Pratt");
pratt.introduceSelf(); // 'My name is Pratt.'
```

このような機能（メソッドが同じ名前で、異なるクラスで異なる実装を持つこと）を **ポリモーフィズム** と呼びます。サブクラスのメソッドがスーパークラスの実装を置き換える場合、サブクラスがスーパークラスのバージョンを**上書きする**と言います。

カプセル化
-----

オブジェクトは、それを使用したい他のコードにインターフェイスを提供しますが、自分自身で内部状態を保持します。オブジェクトの内部状態は **非公開** に保たれ、他のオブジェクトからはアクセスできず、オブジェクト自身のメソッドによってのみアクセスできることを意味します。オブジェクトの内部状態を非公開にすること、そして一般に、その公開インターフェイスと非公開の内部状態を明確に分けることを、**カプセル化**と呼びます。

これは有益な機能で、プログラマーがオブジェクトを使用するコードをすべて探して更新することなく、オブジェクトの内部実装を変更することができます。

例えば、2 年生以上の学生がアーチェリーを学ぶことを許可されているとします。これは、学生の `year` プロパティを公開すれば、他のコードはその学生がそのコースを取ることができるかどうかを判断することができるように実装できます。

```js
if (student.year > 1) {
  // 学生がクラスに入れる
}
```

問題は、もし生徒がアーチェリーを学ぶことを許可する基準を変更することにした場合、例えば親や 保護者からの許可も必要とした場合、このテストを実行するシステム内のすべての場所を更新する必要があることです。そこで、`Student` オブジェクトに `canStudyArchery()` メソッドを用意し、1 か所でロジックを実装するようにしたほうがよいでしょう。
```

class Student : extends Person
    properties
       year
    constructor
       Student(name, year)
    methods
       introduceSelf()
       canStudyArchery() { return this.year > 1 }
```

```js
if (student.canStudyArchery()) {
  // 学生がクラスに入れる
}
```

そうすれば、アーチェリーの履修規則を変更したくなったとき、`Student` クラスを更新するだけで、それを使用するコードはすべて動作するようになります。

多くの OOP 言語では、いくつかのプロパティを `private` としてマークすることで、他のコードがオブジェクトの内部状態にアクセスするのを防ぐことができます。これにより、オブジェクトの外のコードがそれらにアクセスしようとすると、エラーが発生するようになります。
```

class Student : extends Person
    properties
       private year
    constructor
        Student(name, year)
    methods
       introduceSelf()
       canStudyArchery() { return this.year > 1 }

student = new Student('Weber', 1)
student.year // error: 'year' is a private property of Student
```

このようにアクセスを強制しない言語では、プログラマーは、名前をアンダースコアで始めるなどの命名規則を使用して、プロパティがプライベートとみなされることを示します。

OOP と JavaScript
----------------

この記事では、Java や C++ などの言語で実装されているクラスベースのオブジェクト指向プログラミングの基本的な機能のいくつかを記述しました。

前回までの 2 つの記事では、JavaScript の中核となる機能をいくつか見ていきました。コンストラクターとプロトタイプです。これらの機能は、確かに記述した OOP 概念のいくつかと何らかの関連があります。

* JavaScript の**コンストラクター**は、クラス定義のようなもので、オブジェクトの「形状」を定義することができ、そのオブジェクトに格納するメソッドも含めて、単一の場所で定義することができます。しかし、ここでもプロトタイプを使用することができます。例えば、あるメソッドがコンストラクターの `prototype` プロパティで定義されている場合、そのコンストラクターを使用して作成されたすべてのオブジェクトは、そのプロトタイプを介してそのメソッドを取得するので、コンストラクターの中でメソッドを定義する必要はありません。
* **プロトタイプチェーン**は、継承を実装するために自然な方法であるように思えます。例えば、プロトタイプが `Person` である `Student` オブジェクトがあれば、`name` を継承して `introduceSelf()` をオーバーライドすることができます。

しかし、これらの機能と記述した「古典的」な OOP 概念との違いを理解することは価値があります。ここでは、そのうちのいくつかを紹介します。

まず、クラスベースの OOP では、クラスとオブジェクトは別個の構成要素であり、オブジェクトは常にクラスのインスタンスとして作成されます。また、クラスを定義する機能（クラス構文そのもの）と、オブジェクトをインスタンス化する機能（コンストラクター）は区別されています。JavaScript では、関数やオブジェクトリテラルを使用して、別個のクラス定義なしにオブジェクトを作成することができますし、そうすることも多くあります。このため、オブジェクトを使った作業は、古典的な OOP の場合よりもずっと軽量になることがあります。

2 つ目は、プロトタイプチェーンは継承階層のように見え、何かと同じように振る舞いますが、他に異なる点があることです。サブクラスがインスタンス化されると、サブクラスで定義したプロパティと、さらに上の階層で定義したプロパティを結合した単一のオブジェクトが作成されます。プロトタイピングでは、階層の各レベルが別個のオブジェクトで表されており、それらは `__proto__` プロパティを介してリンクされています。プロトタイプチェーンの動作は、継承というよりは**委任**のようなものです。委任とは、あるオブジェクトにタスクの実行を依頼したときに、そのオブジェクト自身がタスクを実行するか、他のオブジェクト（その**委任先**）にタスクの実行を依頼することができるプログラミングパターンです。多くの点で、委任は継承よりも柔軟なオブジェクトの結合方法です（何かというと、実行時に委任先を変更したり完全に置き換えたりすることが可能です）。

とはいえ、コンストラクターとプロトタイプは、JavaScript でクラスベースの OOP パターンを実装するために使用することができます。しかし、継承のような機能を実装するために直接使用するのは難しいので、JavaScript ではプロトタイプモデルの上に指定された、クラスベースの OOP の概念にもっと直接対応する追加機能を提供しています。この機能は次の記事で紹介します。

まとめ
---

この記事では、クラスベースのオブジェクト指向プログラミングの基本的な機能を記述し、JavaScript のコンストラクターとプロトタイプがこれらの概念とどのように比較されるかを簡単に見てきました。

次の記事では、JavaScript がクラスベースのオブジェクト指向プログラミングに対応するために提供している機能について見ていきます。

* 前のページ
* Overview: Objects
* 次のページ


スキルテスト: 条件文 - ウェブ開発を学ぶ

スキルテスト: 条件文
===========

このスキルテストの目的は、あなたがコードでの意思決定 — 条件文を理解したかどうかを判定することです。

**メモ:** 下記のインタラクティブエディターで解答を試すことができますが、コードをダウンロードして、CodePen, jsFiddle, または Glitch などのオンラインツールを使用して、作業することが有益な場合があります。

もし行き詰まったら、私たちに助けを求めてください。このページの下にある評価またはさらなる支援の節をご覧ください。

**メモ:** 下記の例では、コードにエラーがある場合、ページ上の結果パネルに出力され、答え合わせをするのに役立ちます（ダウンロード版の場合は、ブラウザーの JavaScript コンソールに出力されます）。

条件文 1
-----

このタスクでは、2 つの変数が提供されます。

* `season` — 現在の季節を示す文字列が格納されます。
* `response` — 初期化されていない状態で始まりますが、後に出力パネルに表示されるレスポンスを格納するために使用されます。

私たちは、`season` が文字列 "summer" を格納しているかどうかを調べる条件を作成し、もし格納している場合は `response` に文字列を割り当てて、ユーザーに季節に関する適切なメッセージを表示させるようにしたいと考えています。そうでない場合は、 `response` に一般的な文字列を割り当てて、ユーザーに季節が何であるかわからないことを指示しなければなりません。

最後に、`season` が文字列 "winter" を格納するかどうかを調べる別のテストを追加し、再び `response` に適切な文字列を割り当てる必要があります。

下記のコードを更新して、完了した例を再現してみてください。

このタスクの最初の状態をダウンロードして、自分のエディターまたはオンラインエディターで作業してください。

条件文 2
-----

このタスクでは、3 つの変数が提供されます。

* `machineActive` — 応答装置のスイッチがオンになっているかどうかのコンテナー (`true`/`false`) が格納されます。
* `score` — 想像上のゲームにおけるあなたのスコアを格納します。このスコアは応答装置に供給され、あなたがどれだけうまくできたかを示すレスポンスを提供します。
* `response` — 初期化されていない状態で始まりますが、後に出力パネルに表示されるレスポンスを格納するために使用されます。

マシンの電源が入っているかどうかを調べて、もし入っていなければ `response` 変数にメッセージを入れて、ユーザーにマシンの電源を入れるように指示する `if...else` 構造を作成する必要があります。

最初の構造の中に、もしマシンの電源が入っていれば、score の値に応じて適切なメッセージを `response` 変数に格納する `if...else if...else` を入れ子にしておく必要があります。異なる形のテスト(とその結果のレスポンス)は以下の通りです。

* 点数が 0 未満または 100 を超える場合 — "これは不可能です。エラーが発生しました"。
* 0 から 19 点 — "ひどい点数だ。完全に失敗だ！"
* 20 から 39 点 — "いくらか知っているようだが、かなり悪い点数だ。改善が必要だ。"
* 40 から 69 点 — "悪くない仕事をしましたね！"
* 70 から 89 点 — "素晴らしい点数だ、実によく分かっている"
* 90 から 100 点 — "すごい点数だね。カンニングしてない？本当？"

下記のライブコードを更新して、完了例を再現してみてください。コードを入力したら、 `machineActive` を `true` に変更して、これがうまく動作するかどうか試してみてください。

このタスクの最初の状態をダウンロードして、自分のエディターまたはオンラインエディターで作業してください。

条件文 3
-----

このタスクでは、2 つ目のタスクで書いたコードを、内側の `if...else if...else` を書き換えて、代わりに `switch` 文を使用する必要があります。

下記のライブコードを更新して、完了した例を再現してみてください。

このタスクの最初の状態をダウンロードして、自分のエディターまたはオンラインエディターで作業してください。

条件文 4
-----

最後のタスクでは、4 つの変数が提供されます。

* `machineActive` - ログインマシンの電源が入っているかどうかのコンテナー (`true`/`false`) が格納されています。
* `pwd` - ユーザーのログインパスワードが格納されています。
* `machineResult` - 初期化されていない状態で始まりますが、後にマシンの電源が入ったかどうかをユーザーに知らせるために、出力パネルに表示されるレスポンスを格納するために使用されます。
* `pwdResult` - 初期化されていない状態で始まりますが、後に出力パネルに表示されるレスポンスを格納するために使用され、ログインが成功したかどうかをユーザーに知らせます。

マシンのスイッチがオンになっているかどうかを調べる `if...else` 構造を作成し、 `machineResult` 変数に、マシンがオンになっているかオフになっているかをユーザーに指示するメッセージを格納したいと思います。

マシンの電源が入っている場合、2 つ目の条件も実行して、 `pwd` が `cheese` と等しいかどうかを調べます。もしそうなら、 `pwdResult` に文字列を割り当てて、ユーザーにログインに成功したことを指示します。そうでない場合は、`pwdResult` に異なる形の文字列を割り当てて、ログインに失敗したことをユーザーに指示しなければなりません。これを単一の行で、`if...else` 構造でないものを使用してほしいと思います。

下記のライブコードを更新して、完了した例を再現してみてください。

このタスクの最初の状態をダウンロードして、自分のエディターまたはオンラインエディターで作業してください。

評価またはさらなる支援
-----------

これらの例は、上のインタラクティブエディターで練習することができます。

もしあなたが、自分の作品を評価してほしい、あるいは行き詰っているので支援を要請したい場合。

1. CodePen, jsFiddle, または Glitch のようなオンライン共有エディターに あなたの作品を入れましょう。コードは自分で書いてもいいですし、上の節でリンクされている出発点のファイルを使用することもできます。
2. MDN Discourse forum Learning category に、評価や支援を依頼する投稿をします。あなたの投稿には以下のものを含めてください。
    * "Assessment wanted for Conditionals 1 skill test" のような説明的なタイトル。
    * あなたがすでに試したこと、そして私たちに何をしてほしいかについての詳細（例: 行き詰まり、支援を必要とする場合、または評価を希望する場合）。
    * 評価したい、または支援が必要な例へのリンクを、オンライン共有エディター（上記の手順 1 で述べたとおり）にて提供します。これは取得するのに良い習慣です。もしあなたがコードを見ることができなければ、コーディングの問題で誰かを支援するのはとても難しいことです。
    * 実際の課題または評価ページへのリンクで、あなたが支援したい質問を探すことができます。