aboutsummaryrefslogtreecommitdiff
path: root/files/ja/conflicting/learn/javascript/objects/index.html
blob: cbe9e10a0abe2e1dddc5eaa58cb83caf82c273e3 (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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
---
title: オブジェクト指向 JavaScript 入門
slug: Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
tags:
  - Constructor
  - Encapsulation
  - Inheritance
  - Intermediate
  - JavaScript
  - Members
  - Namespace
  - OOP
  - Object
  - Object-Oriented
translation_of: Learn/JavaScript/Objects
translation_of_original: Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
---
<div>{{jsSidebar("Introductory")}}</div>

<p>オブジェクト指向を追求することで、JavaScript は強力かつ柔軟な{{Glossary("OOP", "オブジェクト指向プログラミング")}}能力を特色としています。この記事ではまずオブジェクト指向プログラミングの入門から始め、JavaScript のオブジェクトモデルの復習、そして最後に JavaScript のオブジェクト指向プログラミングの概念を説明します。</p>

<h2 id="JavaScript_review" name="JavaScript_review">JavaScript の復習</h2>

<p>変数、型、関数、スコープといった JavaScript の概念について自信がないのでしたら、<a href="/ja/docs/Web/JavaScript/A_re-introduction_to_JavaScript">JavaScript「再」入門</a>で該当するトピックをご覧いただくとよいでしょう。また、<a href="/ja/docs/Web/JavaScript/Guide">JavaScript ガイド</a>もご覧ください。</p>

<h2 id="Object-oriented_programming" name="Object-oriented_programming">オブジェクト指向プログラミング</h2>

<p>オブジェクト指向プログラミング (OOP) は、実世界を元にしたモデルの作成に{{glossary("abstraction", "抽象化")}}を使用する、プログラミングのパラダイムです。OOP は{{glossary("modularity", "モジュラリティ")}}{{glossary("polymorphism", "ポリモーフィズム")}}{{glossary("encapsulation", "カプセル化")}}といった、これまでに確立されたパラダイム由来の技術を複数使用しています。今日、人気がある多くのプログラミング言語 (Java、JavaScript、C#、C++、Python、PHP、Ruby、Objective-C など) が OOP をサポートしています。</p>

<p>OOP はソフトウェアを関数の集まりや単なるコマンドのリスト(これまでの伝統的な見方)としてではなく、協調して動作するオブジェクトの集まりであると考えます。OOP では、各々のオブジェクトがメッセージを受信し、データを処理し、また他のオブジェクトへメッセージを送信できます。各々のオブジェクトは明確な役割や責任を持つ、独立した小さな機械であると見なせます。</p>

<p>OOP はプログラミングにおける柔軟性や保守性の向上を促し、大規模ソフトウェアエンジニアリングにおいて広く普及しています。OOP はモジュラリティを強く重視しているため、オブジェクト指向によるコードは開発をシンプルにします。また、コードを後から理解することが容易になります。オブジェクト指向によるコードはモジュラリティが低いプログラミング方法よりも、直接的な分析、コーディング、複雑な状況や手続きの理解を促進します。<a href="#cite-1"><sup>1</sup></a></p>

<h2 id="Terminology" name="Terminology">用語集</h2>

<dl>
 <dt>{{Glossary("Namespace", "ネームスペース")}} (名前空間)</dt>
 <dd>開発者があらゆる機能をアプリケーション固有の一意な名前にまとめることができる一種の容器のことです。</dd>
 <dt>{{Glossary("Class", "クラス")}}</dt>
 <dd>オブジェクトの特性を定義するものです。クラスは、オブジェクトのプロパティやメソッドを定義するテンプレートです。</dd>
 <dt>{{Glossary("Object", "オブジェクト")}}</dt>
 <dd>クラスの実体です。</dd>
 <dt>{{Glossary("Property", "プロパティ")}}</dt>
 <dd>「色」などといったオブジェクトの特性です。</dd>
 <dt>{{Glossary("Method", "メソッド")}}</dt>
 <dd>「歩く」などといった、オブジェクトの能力です。これは、クラスに関連付けられたサブルーチンや関数です。</dd>
 <dt>{{Glossary("Constructor", "コンストラクタ")}}</dt>
 <dd>インスタンス化するときに呼び出されるメソッドです。コンストラクタの名前は通常、クラスの名前と同じです。</dd>
 <dt>{{Glossary("Inheritance", "継承")}}</dt>
 <dd>あるクラスが別のクラスから特性を引き継ぐことを指します。</dd>
 <dt>{{Glossary("Encapsulation", "カプセル化")}}</dt>
 <dd>データと、そのデータを使用するメソッドとをまとめる手法のことです。</dd>
 <dt>{{Glossary("Abstraction", "抽象化")}}</dt>
 <dd>実世界のモデルが、オブジェクトの複雑な継承、メソッド、プロパティの集合体によって適切に再現されている状態を指します。</dd>
 <dt>{{Glossary("Polymorphism", "ポリモーフィズム")}}</dt>
 <dd>Poly は "<em>many</em>"、morphism は "<em>forms</em>" を意味します。別々のクラスが同じメソッドやプロパティを定義可能であることを表します。</dd>
</dl>

<p>オブジェクト指向プログラミングのより広範な説明については、Wikipedia の {{interwiki("wikipedia", "オブジェクト指向プログラミング")}} をご覧ください。</p>

<h2 id="Prototype-based_programming" name="Prototype-based_programming">プロトタイプベースプログラミング</h2>

<p>プロトタイプベースのプログラミングはクラスを使用せず、既存の<strong>プロトタイプ</strong>オブジェクトをデコレート(あるいは拡張)してそのオブジェクトの持つ挙動を再利用する(クラスベースの言語における継承と同等)ことで実現される OOP モデルです(クラスレス、プロトタイプ指向、あるいはインスタンスベースプログラミングとも呼ばれます)。</p>

<p>プロトタイプベース言語として先駆けの(そしてもっとも正統な)代表例は、David Ungar 氏と Randall Smith 氏によって開発された {{interwiki("wikipedia", "Self")}} です。とはいえ、クラスレスのプログラミングスタイルは最近ますます人気が高まり、JavaScript、Cecil、NewtonScript、Io、MOO、REBOL、Kevo、Squeak (ソフトウェア Morphic のコンポーネント操作の際の Viewer フレームワークとして使われています)などのプログラミング言語に採用されました。</p>

<h2 id="JavaScript_object_oriented_programming" name="JavaScript_object_oriented_programming">JavaScript のオブジェクト指向プログラミング</h2>

<h3 id="Namespace" name="Namespace">ネームスペース</h3>

<p>ネームスペース(名前空間)とは、開発者が一意なアプリケーション固有の名前を付けて、機能をまとめることができる一種の容器です。<strong>JavaScript では、ネームスペースはメソッド、プロパティ、オブジェクトを包含する別のオブジェクトとなります。</strong></p>

<p>{{note('JavaScript では通常のオブジェクトとネームスペースとの間に、言語レベルの違いがない点に留意することが重要です。これは他の多くのオブジェクト指向言語とは異なっており、新たな JavaScript プログラマを混乱させることがあります。')}}</p>

<p>JavaScript でネームスペースを作成する考え方はシンプルです。グローバルオブジェクトをひとつ作成して、すべての変数、メソッド、関数をそのオブジェクトのプロパティとすればよいのです。ネームスペースを使用すると、アプリケーション内で名前が衝突する可能性が低下します。これは各アプリケーションのオブジェクトが、アプリケーションで定義したグローバルオブジェクトのプロパティとなるからです。</p>

<p>MYAPP という名前のグローバルオブジェクトを作成しましょう :</p>

<pre class="brush: js">// グローバルネームスペース
var MYAPP = MYAPP || {};</pre>

<p>上記のサンプルコードでは、始めに MYAPP が(同じファイルまたは別のファイルで)すでに定義されているかを確認します。定義されている場合は、既存の MYAPP グローバルオブジェクトを使用します。定義されていない場合はメソッド、関数、変数、オブジェクトをカプセル化する、MYAPP という名前の空のオブジェクトを作成します。</p>

<p>サブネームスペースも作成できます(グローバルオブジェクトを最初に定義する必要があることに注意):</p>

<pre class="brush: js">// サブネームスペース
MYAPP.event = {};</pre>

<p>ネームスペースを作成して変数、関数、メソッドを追加する構文は以下のようになります :</p>

<pre class="brush: js">// 共通のメソッドやプロパティ向けに MYAPP.commonMethod という名前のコンテナを作成
MYAPP.commonMethod = {
  regExForName: "", // 名前を検証するための正規表現を定義
  regExForPhone: "", // 電話番号を検証するための正規表現を定義
  validateName: function(name){
    // 名前に対してなんらかの処理を行う。"this.regExForName" を使用して
    // 変数 regExForName にアクセス可能
  },

  validatePhoneNo: function(phoneNo){
    // 電話番号に対してなんらかの処理を行う
  }
}

// オブジェクトとともにメソッドを定義する
MYAPP.event = {
    addListener: function(el, type, fn) {
    // 処理
    },
    removeListener: function(el, type, fn) {
    // 処理
    },
    getEvent: function(e) {
    // 処理
    }

    // 他のメソッドやプロパティを追加できる
}

// addListener メソッドを使用する構文:
MYAPP.event.addListener("yourel", "type", callback);</pre>

<h3 id="Standard_built-in_objects" name="Standard_built-in_objects">標準ビルトインオブジェクト</h3>

<p>JavaScript は、例えば <code>Math</code><code>Object</code><code>Array</code><code>String</code> といったコアに組み込まれたオブジェクトがあります。以下の例では、乱数を取得するために <code>Math</code> オブジェクトの <code>random()</code> メソッドを使用する方法を示したものです。</p>

<pre class="brush: js">console.log(Math.random());
</pre>

<div class="note"><strong>註:</strong> この例、および以降の例では、{{domxref("console.log()")}} という名前の関数がグローバルで定義されていると仮定しています。実際は、<code>console.log()</code> 関数は JavaScript そのものの一部ではありませんが、多くのブラウザがデバッグ用に実装しています。</div>

<p>JavaScript におけるコアオブジェクトの一覧については、<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects">JavaScript リファレンスの標準ビルトインオブジェクト</a>をご覧ください。</p>

<p>JavaScript ではすべてのオブジェクトが <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a> オブジェクトのインスタンスであり、それゆえに Object の全プロパティおよび全メソッドを継承します。</p>

<h3 id="Custom_objects" name="Custom_objects">カスタムオブジェクト</h3>

<h4 id="The_class" name="The_class">クラス</h4>

<p>JavaScript はプロトタイプベースの言語であり、C++ や Java でみられる <code>class</code> 文がありません。これは時に、<code>class</code> 文を持つ言語に慣れているプログラマを混乱させます。その代わりに、JavaScript ではクラスのコンストラクタとして関数を使用します。クラスの定義は、関数の定義と同じほど簡単です。以下の例では、空のコンストラクタを使って Person という名前の新たなクラスを定義しています。</p>

<pre class="brush: js">var Person = function () {};
</pre>

<h4 id="The_object_(class_instance)" name="The_object_(class_instance)">オブジェクト(クラスのインスタンス)</h4>

<p><code>obj</code> オブジェクトの新たなインスタンスを生成するには <code>new obj</code> 文を使用し、その結果(<code>obj</code> 型を持つ)を、後からアクセスするための変数に代入します。</p>

<p>前出の例で、<code>Person</code> という名前のクラスを定義しました。以下の例では、2 つのインスタンス(<code>person1</code><code>person2</code>)を生成しています。</p>

<pre class="brush: js">var person1 = new Person();
var person2 = new Person();
</pre>

<div class="note"><strong>註:</strong> 初期化されていないインスタンスを生成する、新たに追加されたインスタンス化方法については、 {{jsxref("Object.create()")}} をご覧ください。</div>

<h4 id="The_constructor" name="The_constructor">コンストラクタ</h4>

<p>コンストラクタは、インスタンス化の際(オブジェクトのインスタンスが生成されたとき)に呼び出されます。コンストラクタは、クラスのメソッドです。JavaScript では、関数がオブジェクトのコンストラクタとして働きます。したがって、コンストラクタメソッドを明示的に定義する必要はありません。クラス内で定義されたすべてのアクションが、インスタンス化の際に実行されます。</p>

<p>コンストラクタはオブジェクトのプロパティの設定や、オブジェクトの使用準備を行うメソッドの呼び出しを行うために使用されます。クラスのメソッドの追加やメソッドの定義は別の構文を使用して行うことについては、後ほど説明します。</p>

<p>以下の例では <code>Person</code> をインスタンス化する際に、コンストラクタがメッセージをログに出力します。</p>

<pre class="brush: js">var Person = function () {
  console.log('instance created');
};

var person1 = new Person();
var person2 = new Person();
</pre>

<h4 id="The_property_(object_attribute)" name="The_property_(object_attribute)">プロパティ(オブジェクトの属性)</h4>

<p>プロパティは、クラス内にある変数です。オブジェクトのインスタンスはすべて、それらのプロパティを持ちます。プロパティがそれぞれのインスタンスで作成されるように、プロパティはコンストラクタ(関数)内で設定されます。</p>

<p>カレントオブジェクトを示す <code>this</code> キーワードを使用して、クラス内でプロパティを扱うことができます。クラス外からプロパティにアクセス(読み取りや書き込み)するには、<code>InstanceName.Property</code> という構文を使用します。これは C++、Java、その他の言語と同じ構文です(クラスの内部では、プロパティの値の取得や設定に <code>this.Property</code> 構文を使用します)。</p>

<p>以下の例では、<code>Person</code> クラスをインスタンス化する際に <code>firstName</code> プロパティを定義しています:</p>

<pre class="brush: js">var Person = function (firstName) {
  this.firstName = firstName;
  console.log('Person instantiated');
};

var person1 = new Person('Alice');
var person2 = new Person('Bob');

// オブジェクトの firstName プロパティを表示する
console.log('person1 is ' + person1.firstName); // "person1 is Alice" と出力
console.log('person2 is ' + person2.firstName); // "person2 is Bob" と出力
</pre>

<h4 id="The_methods" name="The_methods">メソッド</h4>

<p>メソッドは関数です(また、関数と同じように定義されます)が、他はプロパティと同じ考え方に従います。メソッドの呼び出しはプロパティへのアクセスと似ていますが、メソッド名の終わりに <code>()</code> を付加して、引数を伴うことがあります。メソッドを定義するには、クラスの <code>prototype</code> プロパティの名前付きプロパティに、関数を代入します。関数を代入した名前を使用して、オブジェクトのメソッドを呼び出すことができます。</p>

<p>以下の例では、<code>Person</code> クラスで <code>sayHello()</code> メソッドを定義および使用しています。</p>

<pre class="brush: js">var Person = function (firstName) {
  this.firstName = firstName;
};

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.firstName);
};

var person1 = new Person("Alice");
var person2 = new Person("Bob");

// Person の sayHello メソッドを呼び出す
person1.sayHello(); // "Hello, I'm Alice" と出力
person2.sayHello(); // "Hello, I'm Bob" と出力
</pre>

<p>JavaScript のメソッドはオブジェクトにプロパティとして割り付けられた通常の関数であり、「状況に関係なく」呼び出せます。以下のサンプルコードについて考えてみましょう:</p>

<pre class="brush: js">var Person = function (firstName) {
  this.firstName = firstName;
};

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.firstName);
};

var person1 = new Person("Alice");
var person2 = new Person("Bob");
var helloFunction = person1.sayHello;

// "Hello, I'm Alice" と出力
person1.sayHello();

// "Hello, I'm Bob" と出力
person2.sayHello();

// "Hello, I'm undefined" と出力
// (strict モードでは TypeError で失敗する)
helloFunction();

// true と出力
console.log(helloFunction === person1.sayHello);

// true と出力
console.log(helloFunction === Person.prototype.sayHello);

// "Hello, I'm Alice" と出力
helloFunction.call(person1);</pre>

<p>この例で示すように、<code>sayHello</code> 関数を参照しているもの(<code>person1</code><code>Person.prototype</code><code>helloFunction</code> 変数など)すべてが、<strong>同一の関数</strong>を示しています。関数を呼び出しているときの <code>this</code> の値は、関数の呼び出し方に依存します。もっとも一般的な、オブジェクトのプロパティから関数にアクセスする形式 (<code>person1.sayHello()</code>) で <code>this</code> を呼び出すときは、その関数を持つオブジェクト (<code>person1</code>) を <code>this</code> に設定します。これが、<code>person1.sayHello()</code> で名前として "Alice"、<code>person2.sayHello()</code> で名前として "Bob" が使用される理由です。一方、他の方法で呼び出す場合は <code>this</code> に設定されるものが変わります。変数 (<code>helloFunction()</code>) から <code>this</code> を呼び出すと、グローバルオブジェクト(ブラウザでは <code>window</code>)を <code>this</code> に設定します。このオブジェクトは(おそらく)<code>firstName</code> プロパティを持っていないため、"Hello, I'm undefined" になります(これは loose モードの場合です。<a href="/ja/docs/Web/JavaScript/Reference/Strict_mode" title="Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode">strict モード</a>では異なる結果(エラー)になりますが、ここでは混乱を避けるために詳細は割愛します)。あるいは、例の最後で示したように <code>Function#call</code> (または <code>Function#apply</code>)を使用して、<code>this</code> を明示的に設定できます。</p>

<div class="note"><strong>註:</strong> <code>this</code> について、詳しくは {{jsxref("Global_Objects/Function/call","Function#call")}} および {{jsxref("Global_Objects/Function/apply","Function#apply")}} をご覧ください。</div>

<h4 id="Inheritance" name="Inheritance">継承</h4>

<p>継承は、1 つ以上のクラスを特化したバージョンとしてクラスを作成する方法です(<strong>JavaScript は単一継承のみサポートしています</strong>)。特化したクラスは一般的に<strong></strong>と呼ばれ、またそれ以外のクラスは一般的に<strong></strong>と呼ばれます。JavaScript では親クラスのインスタンスを子クラスに代入して、特化させることにより継承を行います。現代のブラウザでは、継承の実装に {{jsxref("Global_Objects/Object/create","Object.create","#Classical_inheritance_with_Object.create()")}} を使用することもできます。</p>

<div class="note">
<p><strong>註:</strong> JavaScript は子クラスの <code>prototype.constructor</code>{{jsxref("Global_Objects/Object/prototype","Object.prototype")}} をご覧ください)を検出しないため、手動で明示しなければなりません。Stackoverflow に投稿された質問 "<a href="http://stackoverflow.com/questions/8453887/why-is-it-necessary-to-set-the-prototype-constructor">Why is it necessary to set the prototype constructor?</a>" をご覧ください。</p>
</div>

<p>以下の例では、<code>Person</code> の子クラスとして <code>Student</code> クラスを定義しています。そして、<code>sayHello()</code> メソッドの再定義と <code>sayGoodBye()</code> メソッドの追加を行っています。</p>

<pre class="brush: js">// Person コンストラクタを定義する
var Person = function(firstName) {
  this.firstName = firstName;
};

// Person.prototype にメソッドを 2 つ追加する
Person.prototype.walk = function(){
  console.log("I am walking!");
};

Person.prototype.sayHello = function(){
  console.log("Hello, I'm " + this.firstName);
};

// Student コンストラクタを定義する
function Student(firstName, subject) {
  // 親のコンストラクタを呼び出す。呼び出しの際に "this" が
  // 適切に設定されるようにする (Function#call を使用)
  Person.call(this, firstName);

  // Student 固有のプロパティを初期化する
  this.subject = subject;
};

// Person.prototype を継承する、Student.prototype オブジェクトを作成する
// 註: ここでよくある間違いが、Student.prototype を生成するために
// "new Person()" を使用することです。これは様々な理由で間違っていますが、
// まずこれでは Person の "firstName" 引数に渡すものがありません。
// Person を呼び出す正しい場所はこれより前の、
// Student から呼び出します。
Student.prototype = Object.create(Person.prototype); // 以下の注釈を参照

// "constructor" プロパティが Student を指すように設定する
Student.prototype.constructor = Student;

// "sayHello" メソッドを置き換える
Student.prototype.sayHello = function(){
  console.log("Hello, I'm " + this.firstName + ". I'm studying "
              + this.subject + ".");
};

// "sayGoodBye" メソッドを追加する
Student.prototype.sayGoodBye = function(){
  console.log("Goodbye!");
};

// 使用例:
var student1 = new Student("Janet", "Applied Physics");
student1.sayHello();   // "Hello, I'm Janet. I'm studying Applied Physics."
student1.walk();       // "I am walking!"
student1.sayGoodBye(); // "Goodbye!"

// instanceof が正常に機能するかをチェック
console.log(student1 instanceof Person);  // true
console.log(student1 instanceof Student); // true
</pre>

<p><code>Student.prototype = Object.create(Person.prototype);</code> という行について :<br>
 {{jsxref("Global_Objects/Object/create","Object.create")}} が存在しない古い JavaScript エンジンでは、「{{原語併記("ポリフィル","polyfill")}}」 ("shim" とも呼ばれます。リンク先の記事をご覧ください)または同様の結果になる以下のような関数を使用できます。:</p>

<pre class="brush: js">function createObject(proto) {
    function ctor() { }
    ctor.prototype = proto;
    return new ctor();
}

// 使用法:
Student.prototype = createObject(Person.prototype);
</pre>

<div class="note"><strong>註:</strong> Object.create や古いエンジン向けの shim が何を行っているかについては、{{jsxref("Global_Objects/Object/create","Object.create")}} をご覧ください。</div>

<p>オブジェクトをインスタンス化する方法を問わずに、<code>this</code> の参照先を適切に指定するのは時に難しいものです。ですが、これを容易にするシンプルなイディオムがあります。</p>

<pre class="brush: js">var Person = function(firstName) {
  if (this instanceof Person) {
    this.firstName = firstName;
  } else {
    return new Person(firstName);
  }
}
</pre>

<h4 id="Encapsulation" name="Encapsulation">カプセル化</h4>

<p>前の例では、<code>Person</code> クラスによる <code>walk()</code> メソッドの実装状況を <code>Student</code> が知らなくても、そのメソッドを使用できました。<code>Student</code> クラスは変更の必要がない限り、そのメソッドを明示的に定義する必要はありません。すべてのクラスのデータとメソッドがひとつのユニットに収められていることから、これを<strong>カプセル化</strong>と呼びます。</p>

<p>情報を隠蔽することは、他の言語でも <code>private</code> または <code>protected</code> なメソッドやプロパティという形で一般的な機能です。JavaScript でも同様のことをシミュレートできますが、オブジェクト指向プログラミングに必須というわけではありません。<a href="#cite-2"><sup>2</sup></a></p>

<h4 id="Abstraction" name="Abstraction">抽象化</h4>

<p>抽象化は、取り組んでいる問題の箇所を継承(特殊化)や合成によってモデル化することを可能にする仕組みです。JavaScript では継承によって特殊化を、クラスのインスタンスを別のオブジェクトの属性値にすることで合成を実現しています。</p>

<p>JavaScript の <code>Function</code> クラスは <code>Object</code> クラスから継承しています(これはモデルを特殊化している一例です)。また、<code>Function.prototype</code> プロパティは <code>Object</code> のインスタンスです (これは合成の一例です)。</p>

<pre class="brush: js">var foo = function () {};

// "foo is a Function: true" と出力
console.log('foo is a Function: ' + (foo instanceof Function));

// "foo.prototype is an Object: true" と出力
console.log('foo.prototype is an Object: ' + (foo.prototype instanceof Object));</pre>

<h4 id="Polymorphism" name="Polymorphism">ポリモーフィズム</h4>

<p>すべてのメソッドやプロパティが <code>prototype</code> プロパティの内部で実装されているのと同じように、異なるクラスで同じ名前のメソッドを定義できます。メソッドは 2 つのクラスに親子関係(すなわち、あるクラスが別のクラスから継承されている)がない限り、自身が定義されたクラスに収められます。</p>

<h2 id="Notes" name="Notes">注記</h2>

<p>これらは JavaScript でオブジェクト指向プログラミングを実装する唯一の方法ではありません。この点で JavaScript はとても融通がききます。同様に、ここで示した技術は言語ハックをまったくしていませんし、他言語のオブジェクト理論における実装を模倣してもいません。</p>

<p>このほかにも、JavaScript によるより高度なオブジェクト指向プログラミングのテクニックがありますが、この入門記事で扱う範囲を超えます。</p>

<h2 id="References" name="References">参考情報</h2>

<ol>
 <li>Wikipedia: "<a href="http://en.wikipedia.org/wiki/Object-oriented_programming" name="cite-1">Object-oriented programming</a>" (<a href="http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0">日本語版</a>)</li>
 <li>Wikipedia: "<a href="http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29" name="cite-2">Encapsulation (object-oriented programming)</a>" (<a href="http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96">日本語版</a>)</li>
</ol>