aboutsummaryrefslogtreecommitdiff
path: root/files/ja/learn/javascript/objects/object-oriented_js/index.html
blob: 50ced468d547f046644ff21f4f217ce87a5d64c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
---
title: 初心者のためのオブジェクト指向 JavaScript
slug: Learn/JavaScript/Objects/Object-oriented_JS
tags:
  - Beginner
  - Create
  - JavaScript
  - OOJS
  - OOP
  - オブジェクト
  - オブジェクト指向
  - 学習
  - 記事
translation_of: Learn/JavaScript/Objects/Object-oriented_JS
---
<div>{{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div>

<p class="summary">基礎が片付いたところで、オブジェクト指向 JavaScript (OOJS) について取り上げます。この記事ではオブジェクト指向プログラミング (OOP) の基本的な視点を説明し、 JavaScript がどのようにコンストラクター関数を通じてオブジェクトクラスをエミュレートしているか、またどのようにオブジェクトインスタンスを生成しているかを紹介します。</p>

<table class="learn-box standard-table">
 <tbody>
  <tr>
   <th scope="row">前提知識:</th>
   <td>基礎的なコンピュータリテラシー、基礎的な HTML と CSS の理解、JavaScript (<a href="/ja/docs/Learn/JavaScript/First_steps">JavaScript の第一歩</a><a href="/ja/docs/Learn/JavaScript/Building_blocks">JavaScript の構成要素</a>を参照) および OOJS (<a href="/ja/docs/Learn/JavaScript/Objects/Basics">JavaScript オブジェクトの基本</a>を参照)の基礎知識。</td>
  </tr>
  <tr>
   <th scope="row">目標:</th>
   <td>オブジェクト指向プログラミングの基本理論、どのようにそれが JavaScript (「すべてはオブジェクトである」) に関連しているか、どのようにコンストラクターがオブジェクトインスタンスを生成しているかを理解する。</td>
  </tr>
 </tbody>
</table>

<h2 id="Object-oriented_programming_—_the_basics" name="Object-oriented_programming_—_the_basics">オブジェクト指向プログラミング - その基本</h2>

<p>はじめに、オブジェクト指向プログラミング (OOP) とは何か、シンプルかつ高レベルな視点を提示します。シンプルと述べたのは、OOP はあっという間にひどく複雑になり得るためで、現時点でそのすべてを論じてしまうと、助けとなるよりもむしろ混乱を生んでしまうことでしょう。OOP の基本的な考え方は、プログラムの中で扱いたい、現実世界の事物を模るためにオブジェクトを使用すること、またはそうしなければ使うことが難しいあるいは不可能だった機能にアクセスするための、シンプルな方法を提供することです。</p>

<p>オブジェクトは、モデル化しようとしている事物に関する情報および、持たせたい機能や動作を表現する、関連したデータとコードを持つことができます。オブジェクトのデータ (しばしば関数も含む) はオブジェクトのパッケージの中 (<strong>名前空間</strong>と呼ばれることがある) に適切に格納されます (<strong>カプセル化</strong>)。オブジェクトは一般に、ネットワークを通じて容易に送信することが可能な、データストアとしても使われます。</p>

<h3 id="Defining_an_object_template" name="Defining_an_object_template">オブジェクトのテンプレートを定義する</h3>

<p>学校の生徒と教師の情報を表示する、シンプルなプログラムを考えてみましょう。特定のプログラミング言語の文脈ではなく、OOP 一般の理論を眺めていきます。</p>

<p>はじめに、<a href="/ja/docs/Learn/JavaScript/Objects/Basics">オブジェクト入門の最初の記事</a>にある、人物の包括的なデータや機能を定義した、Person オブジェクトに戻りましょう。ある人物について知り得る事柄は数多くあります (住所、身長、靴のサイズ、DNA 情報、パスポート番号、顕著な人格特性など) が、このケースでは名前、年齢、性別、趣味を表示することに興味があるだけです。また、このデータに基づいた短い自己紹介や、挨拶をさせられるようにもしましょう。これは<strong>抽象化</strong> — より複雑な事物を、プログラムの目的に沿って簡単に操作できるように、その最も重要な側面を表現する、シンプルなモデルを作ること — として知られています。</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/13889/person-diagram.png" style="display: block; height: 219px; margin: 0px auto; width: 610px;"></p>

<h3 id="Creating_actual_objects" name="Creating_actual_objects">実際のオブジェクトの生成</h3>

<p>このクラスから、<strong>オブジェクトインスタンス</strong>を生成することができます。オブジェクトインスタンスは、クラスで定義されたデータや機能を持ったオブジェクトです。 Person クラスから、何名かの実際の人物を生成します。</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/15163/MDN-Graphics-instantiation-2-fixed.png" style="display: block; height: 702px; margin: 0px auto; width: 695px;"></p>

<p>クラスからオブジェクトインスタンスが生成されるとき、クラスの<strong>コンストラクター関数</strong>が生成のために実行されます。クラスからオブジェクトインスタンスが生成される過程を<strong>インスタンス化</strong>と呼びます。オブジェクトインスタンスは、クラスを<strong>インスタンス化</strong>したものです。</p>

<h3 id="Specialist_classes" name="Specialist_classes">専門のクラス</h3>

<p>このケースで求めているのは、包括的な人物ではなく、より特定のタイプである、教師と生徒です。OOP では、他のクラスを元にした新しいクラスを作ることができます。これらの新しい<strong>子クラス</strong>は、<strong>親クラス</strong>からデータやコード機能を<strong>継承</strong>することができ、すべてのオブジェクトタイプに共通する機能を、重複させるのではなく、再利用することができます。クラス間で機能が異なる場合は、必要に応じて特殊化された機能を直接定義することができます。</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/13881/MDN-Graphics-inherited-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p>

<p>これは実に役立ちます。教師と生徒は名前、性別、年齢のように多数の共通機能を共有しており、これらの機能を一度だけ定義すればいいので便利です。異なるクラスで、同じ機能を分けて定義することもでき、その機能の各定義は異なる名前空間に置かれます。例えば、生徒の挨拶は "Yo, I'm [firstName]" (例:<em>Yo, I'm Sam) という形式とし、一方の教師の挨拶は、より形式的に </em>"Hello, my name is [Prefix] [lastName], and I teach [Subject]." (例:<em>Hello, My name is Mr Griffiths, and I teach Chemistry) のように。</em></p>

<div class="note">
<p><strong></strong>: 同じ機能を複数のオブジェクトタイプが実装する能力のことを示す用語に、<strong>ポリモーフィズム</strong>があります。不思議に感じているかも知れないので念のため。</p>
</div>

<p>子クラスのオブジェクトインスタンスを生成しましょう。例:</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/13885/MDN-Graphics-instantiation-teacher-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p>

<p>記事の続きでは、OOP 理論が JavaScript でどのように実践されているかを見ていきます。</p>

<h2 id="Constructors_and_object_instances" name="Constructors_and_object_instances">コンストラクターとオブジェクトインスタンス</h2>

<p>JavaScript では、オブジェクトやその機能を定義し初期化するために<strong>コンストラクター関数</strong>と呼ばれる特殊な関数を使用します。これは便利です。なぜならオブジェクトをいくつ作成することになるか分からない状況に出くわすでしょうから。コンストラクターは必要な数のオブジェクトを効率的な方法で作成し、必要に応じてデータや関数を付加する手段を提供します。</p>

<p>JavaScript でコンストラクターを通じてクラスを作り、そこからオブジェクトのインスタンスを生成するところを見ていきましょう。まずは、最初のオブジェクトの記事で見た <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a> ファイルの新しいコピーを、ローカルに作成しておいてください。</p>

<h3 id="A_simple_example" name="A_simple_example">シンプルな例</h3>

<ol>
 <li>どのように通常の関数で人物を定義できるかを見てみるところから始めましょう。この関数を <code>script</code> 要素の中に加えてください。

  <pre class="brush: js notranslate">function createNewPerson(name) {
  const obj = {};
  obj.name = name;
  obj.greeting = function() {
    alert('Hi! I\'m ' + obj.name + '.');
  };
  return obj;
}</pre>
 </li>
 <li>この関数を呼び出すことで、新しい人物を生成することができます。次の 3 行をブラウザーの JavaScript コンソールで試してみてください。
  <pre class="brush: js notranslate">const salva = createNewPerson('Salva');
salva.name;
salva.greeting();</pre>
  これも十分上手くいっていますが、やや長ったらしいです。オブジェクトを生成したいと知っているなら、なぜ明示的に空のオブジェクトを生成し、返すことが必要なのでしょうか?幸いにも、 JavaScript はコンストラクター関数という形で、便利なショートカットを提供してくれます。早速作ってみましょう!</li>
 <li>前の関数を、以下のもので置き換えてください。
  <pre class="brush: js notranslate">function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}</pre>
 </li>
</ol>

<p>コンストラクター関数は、 JavaScript 版のクラスです。それは関数に期待される全ての機能を持っていますが、何も返さないし、明示的にオブジェクトを生成しもしないという点に注意してください。基本的には、プロパティとメソッドを定義するだけです。加えて、 <code>this</code> キーワードが使われていることにも注意してください。基本、オブジェクトインスタンスの 1 つが作成されるときにはいつでも、オブジェクトの <code>name</code> プロパティはコンストラクター呼び出しに渡される name 値と等しくなり、 <code>greeting()</code> メソッドもコンストラクター呼び出しに渡される name 値を使用します。</p>

<div class="note">
<p><strong>メモ</strong>: 通常、コンストラクター関数の名前は大文字で始まります。コードの中で、コンストラクター関数がより容易に認識されるようにするための慣習です。</p>
</div>

<p>では、オブジェクトを生成するために、どのようにコンストラクターを呼び出したらよいでしょうか?</p>

<ol>
 <li>次の 2 行を、前のコードの続きに加えてください。
  <pre class="brush: js notranslate">let person1 = new Person('Bob');
let person2 = new Person('Sarah');</pre>
 </li>
 <li>コードを保存し、ブラウザーをリロードして、以下の 4 行を JavaScript コンソールに入れて試してみてください。
  <pre class="brush: js notranslate">person1.name
person1.greeting()
person2.name
person2.greeting()</pre>
 </li>
</ol>

<p>素晴らしい!2 つの新しいオブジェクトが、異なる名前空間の下でページに格納されていることが確認できます。それらのプロパティとメソッドにアクセスするときには、 <code>person1</code> または <code>person2</code> を呼び出すことから始めなければなりません。中に含まれている機能は適切にパッケージ化されており、他の機能と衝突しないようになっています。しかしながら、それらは同じように <code>name</code> プロパティと <code>greeting()</code> メソッドが利用可能です。 2 つのオブジェクトはそれぞれ、生成されたときに割り当てられた、自身の <code>name</code> 値を使っていることに注意してください。これが <code>this</code> を使うことがとても重要である理由の 1 つであり、他の値ではなく、自身の値を使っているのです。</p>

<p>コンストラクターをもう一度呼び出してみましょう。</p>

<pre class="brush: js notranslate">let person1 = new Person('Bob');
let person2 = new Person('Sarah');</pre>

<p>いずれのケースでも、新しいオブジェクトインスタンスを生成したいとブラウザーに伝えるために <code>new</code> キーワードが使われており、その後に、括弧に必要なパラメーターを入れた関数名が続き、その結果が変数に格納されていて、一般的な関数の呼ばれ方とよく似ています。どちらのインスタンスも、次の定義によって生成されています。</p>

<pre class="brush: js notranslate">function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}</pre>

<p>新しいオブジェクトが生成された後、 <code>person1</code> および <code>person2</code> 変数は、次のオブジェクトを格納しています。</p>

<pre class="brush: js notranslate">{
  name: 'Bob',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

{
  name: 'Sarah',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}</pre>

<p>コンストラクター関数を呼び出すとき、毎回 <code>greeting()</code> メソッドを定義していることに注意してください。これは理想的ではありません。これを回避するために、代わりにプロトタイプに関数を定義することができます。後で見てみましょう。</p>

<h3 id="Creating_our_finished_constructor" name="Creating_our_finished_constructor">最終的なコンストラクターの作成</h3>

<p>上で見てきた例は、スタートのためのシンプルな例に過ぎません。次は最終的な <code>Person()</code> コンストラクター関数を作りましょう。</p>

<ol>
 <li>ここまでに挿入したコードを削除し、代わりとなるコンストラクターを追加してください。これはシンプルな例とほぼ同じもので、ほんのわずか複雑になっているだけです。
  <pre class="brush: js notranslate">function Person(first, last, age, gender, interests) {
  this.name = {
     first : first,
     last : last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
  this.bio = function() {
    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  };
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name.first + '.');
  };
}</pre>
 </li>
 <li>ではその下に、コンストラクターからオブジェクトインスタンスを生成するため、次の行を追加してください。
  <pre class="brush: js notranslate">let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);</pre>
 </li>
</ol>

<p>ちょうど以前行ったように、プロパティやメソッドにアクセスできることを確認できます。 JavaScript コンソールの中でやってみましょう。</p>

<pre class="brush: js notranslate">person1['age']
person1.interests[1]
person1.bio()
// etc.</pre>

<div class="note">
<p><strong>メモ</strong>: もしこの工程で何らかのトラブルがあった場合は、あなたのコードを我々のバージョン (<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a><a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">ライブサンプル</a>も) と比べてみてください。</p>
</div>

<h3 id="Further_exercises" name="Further_exercises">さらなる練習</h3>

<p>まずはじめに、さらにいくつかのオブジェクトを生成する独自の行を追加し、オブジェクトインスタンスのメンバーの取得や設定をしてみてください。</p>

<p>加えて、 <code>bio()</code> メソッドにはいくつかの問題点があります。人物が女性である、あるいは他の優先される性別分類の場合でも、その出力には常に "He" という代名詞が含まれています。また、 bio は <code>interests</code> 配列により多くのものが列挙されていても、2 つの趣味しか含みません。このクラス定義 (コンストラクター) の問題を、あなたはどのように修正することができますか?コンストラクター内に任意のコード (恐らく、いくつかの条件分岐やループが必要となるでしょう) を入れてみてください。性別や、趣味の数が 1、2、あるいは 2 よりも多いかどうかによって、文がどのように構築されるべきか考えてみてください。</p>

<div class="note">
<p><strong></strong>: もし行き詰まってしまった場合は、<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">GitHub に答えとなるリポジトリ</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">ライブ</a>) があります。最初はあなた自身で書いてみてください!</p>
</div>

<h2 id="Other_ways_to_create_object_instances" name="Other_ways_to_create_object_instances">オブジェクトインスタンスを生成する他の方法</h2>

<p>ここまで、オブジェクトインスタンスを生成する 2 つの異なる方法を見てきました。<a href="/ja/docs/Learn/JavaScript/Objects/Basics#Object_basics">オブジェクトリテラルの宣言</a>と、上で見たコンストラクター関数の使用です。</p>

<p>これで十分かもしれませんが、他にも方法はあります。ウェブを巡る際に遭遇したときに備えて、よく知っておいてください。</p>

<h3 id="The_Object_constructor" name="The_Object_constructor">Object() コンストラクター</h3>

<p>まず最初に、 <code><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> コンストラクターを新しいオブジェクトの生成のために使うことができます。はい、一般的なオブジェクトにも、空のオブジェクトを生成するコンストラクターがあります。</p>

<ol>
 <li>このコードを JavaScript コンソールに入力してみましょう。
  <pre class="brush: js notranslate">let person1 = new Object();</pre>
 </li>
 <li><code>person1</code> 変数に空のオブジェクトが格納されました。このオブジェクトに、ドット記法とブラケット記法を使ってプロパティを追加することができます。次の例を JavaScript コンソールで試してみましょう。
  <pre class="brush: js notranslate">person1.name = 'Chris';
person1['age'] = 38;
person1.greeting = function() {
  alert('Hi! I\'m ' + this.name + '.');
};</pre>
 </li>
 <li>あらかじめプロパティやメソッドを設定するため、<code>Object()</code> コンストラクターに引数としてオブジェクトリテラルを渡すことも可能です。次のコードを JavaScript コンソールで試してみてください。
  <pre class="brush: js notranslate">let person1 = new Object({
  name: 'Chris',
  age: 38,
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
});</pre>
 </li>
</ol>

<h3 id="Using_the_create_method" name="Using_the_create_method">create() メソッドの使用</h3>

<p>コードの順序についてもコンストラクターが助けとなります。コンストラクターを一箇所で作っておくと、必要に応じてインスタンスを生成することができ、それらがどこから来たものであるか、明瞭です。</p>

<p>しかしながら、特に少数のインスタンスのみを生成する場合に、最初にコンストラクターを作らずにインスタンスを生成することを好む人もいます。JavaScript にはそれを可能とする、<code>create()</code> と呼ばれる組み込みメソッドがあります。それにより、既存のオブジェクトを基にして、新しいオブジェクトを生成することができます。</p>

<ol>
 <li>前のセクションの練習をブラウザーで終えた状態で、こちらを JavaScript コンソールで試してみてください。
  <pre class="brush: js notranslate">let person2 = Object.create(person1);</pre>
 </li>
 <li>次は以下のコードです。
  <pre class="brush: js notranslate">person2.name;
person2.greeting();</pre>
 </li>
</ol>

<p><code>person1</code> を基に <code>person2</code> が生成され、<code>person2</code> では同じプロパティとメソッドが利用可能であることを確認することができます。</p>

<p><code>create()</code> には、IE8 が対応していないという制限があります。つまり、コンストラクターは古いブラウザーに対応したい場合により効果的かもしれません。</p>

<p>いずれ、<code>create()</code> の効果についてより詳細に紹介するつもりです。</p>

<h2 id="あなたのスキルをテストしてみましょう!">あなたのスキルをテストしてみましょう!</h2>

<p>この記事はここまでですが、最も重要な情報を覚えていますか?先に進む前に、この情報を保持しているかどうかを確認するために、さらにいくつかのテストを見つけることができます。<a class="new" href="https://wiki.developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Test_your_skills:_Object-oriented_JavaScript" rel="nofollow">あなたのスキルをテストする: オブジェクト指向 JavaScript</a> を参照してください。</p>

<p>この一連のテストは次の記事で紹介する知識に依存していることに注意してください。なので、試してみる前に、まずそれを読んでみるといいかもしれません。</p>

<h2 id="Summary" name="Summary">まとめ</h2>

<p>この記事はオブジェクト指向の理論の概略を見てきました。これですべてではありませんが、ここで扱っていることに関する考えを提示しました。加えて、オブジェクトのインスタンスを生成する様々な方法を見始めたところです。</p>

<p>次の記事では、 JavaScript オブジェクトのプロトタイプについて紹介します。</p>

<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p>

<h2 id="In_this_module" name="In_this_module">このモジュール内の文書</h2>

<ul>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Basics">オブジェクトの基本</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object-oriented_JS">初心者のためのオブジェクト指向 JavaScript</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object_prototypes">Object のプロトタイプ</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Inheritance">JavaScript での継承</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/JSON">JSON データの操作</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Object_building_practice">オブジェクト作成の練習</a></li>
 <li><a href="/ja/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">バウンスボールに機能を追加する</a></li>
</ul>