diff options
author | Florian Merz <me@fiji-flo.de> | 2021-02-11 12:07:59 +0100 |
---|---|---|
committer | Florian Merz <me@fiji-flo.de> | 2021-02-11 12:07:59 +0100 |
commit | 6ef1fa4618e08426b874529619a66adbd3d1fcf0 (patch) | |
tree | 890e3e27131be010d82ef957fa68db495006cb0e /files/ja/conflicting/learn/javascript | |
parent | 8260a606c143e6b55a467edf017a56bdcd6cba7e (diff) | |
download | translated-content-6ef1fa4618e08426b874529619a66adbd3d1fcf0.tar.gz translated-content-6ef1fa4618e08426b874529619a66adbd3d1fcf0.tar.bz2 translated-content-6ef1fa4618e08426b874529619a66adbd3d1fcf0.zip |
unslug ja: move
Diffstat (limited to 'files/ja/conflicting/learn/javascript')
3 files changed, 619 insertions, 0 deletions
diff --git a/files/ja/conflicting/learn/javascript/building_blocks/events/index.html b/files/ja/conflicting/learn/javascript/building_blocks/events/index.html new file mode 100644 index 0000000000..0c2047bce5 --- /dev/null +++ b/files/ja/conflicting/learn/javascript/building_blocks/events/index.html @@ -0,0 +1,89 @@ +--- +title: Event 属性 +slug: Web/Guide/HTML/Event_attributes +tags: + - Beginner + - Guide + - HTML + - Intermediate + - JavaScript +translation_of: >- + Learn/JavaScript/Building_blocks/Events#Inline_event_handlers_%E2%80%94_don%27t_use_these +translation_of_original: Web/Guide/HTML/Event_attributes +--- +<p><span class="seoSummary">すべての HTML 要素は、特定のイベントが発生したときの JavaScript の実行が許可された属性の集合から成り立ちます。これらは Event 属性と呼ばれ、その属性名には "on" の接頭辞が付きます。</span>例えば、ユーザーが要素をクリックしたときに JavaScript を実行するために、JavaScript を <code>onclick</code> 属性の中に書きます。</p> + +<p>イベントの応答として JavaScript のコードが実行された場合、<code>this</code> スコープは HTML 要素となり、このスコープ内にある <code>event</code> 変数を通して {{domxref("Event")}} オブジェクトにアクセスできます。</p> + +<div class="warning"> +<p><strong>警告:</strong> これらの属性を使うことは避けるべきです。これは HTML を巨大化し可読性を下げます。情報と振る舞いの関心事が正しく分離されておらず、発見が困難なバグを生み出します。その上に、Event 属性の使い方はほとんどの場合、{{domxref("Window")}} オブジェクト上のグローバル関数にスクリプトを晒す原因になります。これはグローバルの名前空間を汚染します。</p> +</div> + +<p>これらの属性が魅力的で簡単に使うことができたとしても、これを使うのは避けるべきです。代わりに、イベントリスナーを追加する為には {{domxref("EventTarget.addEventListener()")}} 関数を使ってください。</p> + +<p>この Event 属性は、'unsafe-inline' キーワードを使わない限りすべてのインラインスクリプトをブロックする<a href="/docs/Security/CSP/Introducing_Content_Security_Policy">コンテンツ・セキュリティ・ポリシー</a>を使うことよって ブロックされる可能性があります。</p> + +<h2 id="Example_using_event_attributes" name="Example_using_event_attributes">Event 属性の使用例</h2> + +<p>この例は {{HTMLElement("div")}} がクリックされる度にテキストを要素に追加します。</p> + +<div class="note"> +<p><strong>注意:</strong> これは、これらの属性の 1 つを使用する例であり、するべきではない方法です。</p> +</div> + +<pre class="brush: html"><!doctype html> +<html> + <head> + <title>Event 属性の例</title> + <script> + function doSomething() { + document.getElementById("thanks").innerHTML += "<p>クリックしてくれてありがとう!</p>"; + } + </script> + </head> + <body> + <div onclick="doSomething();">クリック!</div> + <div id="thanks"></div> + </body> +</html> +</pre> + +<p>この例を実行してみてください:</p> + +<p>{{ EmbedLiveSample('Example_using_event_attributes', '', '', '') }}</p> + +<h2 id="Example_using_event_listeners" name="Example_using_event_listeners">イベントリスナーの使用例</h2> + +<p>代わりに、以下に示すように {{domxref("EventTarget.addEventListener()")}} を使うべきです。</p> + +<pre class="brush: html"><!doctype html> +<html> + <head> + <title>Event 属性の例</title> + <script> + function doSomething() { + document.getElementById("thanks").innerHTML += "<p>クリックしてくれてありがとう!</p>"; + } + + // ページのロードが完了した時に呼ばれる; + // ここは、ページ内の要素にイベントリスナを追加するなど、何でも必要な設定を実行する場所です。 + + function setup() { + document.getElementById("click").addEventListener("click", doSomething, true); + } + // ウィンドウ内のドキュメントのロードが完了したことを知る為の、 + // "load" イベントを受け取る為にイベントリスナを window オブジェクトに追加する + + window.addEventListener("load", setup, true); + </script> + </head> + <body> + <div id="click">クリック!</div> + <div id="thanks"></div> + </body> +</html></pre> + +<p>この動作を以下の例から確認できます:</p> + +<p>{{ EmbedLiveSample('Example_using_event_listeners', '', '', '') }}</p> +<section id="Quick_Links"><ol><li><a href="/ja/docs/Web/API/Event" title="Event インターフェイスは、DOM で発生するイベントを表します。ユーザーによって発生するイベント (マウスやキーボードのイベント) もありますし、API によって発生するイベント (アニメーションの実行が完了したことを示すイベントや、動画再生が一時停止したイベントなど) もあります。さまざまな型のイベントがあり、一部のイベントは基底の Event インターフェイスを基にした他のインターフェイスを使用します。Event 自体は、すべてのイベントで共通のプロパティやメソッドを持ちます。">Event</a></li><li><a href="/ja/docs/Web/API/EventTarget" title="EventTarget は、イベントを受け取り、そのためのリスナーを持つ可能性があるオブジェクトにより実装されたインターフェースです。">EventTarget</a></li><li><a href="/ja/docs/Web/API/EventTarget.addEventListener">EventTarget.addEventListener</a></li></ol></section> diff --git a/files/ja/conflicting/learn/javascript/client-side_web_apis/manipulating_documents/index.html b/files/ja/conflicting/learn/javascript/client-side_web_apis/manipulating_documents/index.html new file mode 100644 index 0000000000..fc2fa7a3b4 --- /dev/null +++ b/files/ja/conflicting/learn/javascript/client-side_web_apis/manipulating_documents/index.html @@ -0,0 +1,149 @@ +--- +title: JavaScript and CSS +slug: Web/Guide/CSS/Getting_started/JavaScript +tags: + - CSS + - 'CSS:Getting_Started' +translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents +translation_of_original: Web/Guide/CSS/Getting_started/JavaScript +--- +<div> + {{CSSTutorialTOC}}</div> +<p>これは <a href="/ja/docs/CSS/Getting_Started" title="https://developer.mozilla.org/ja/CSS/Getting_Started">CSS チュートリアル</a> 第2部の、第 1 章です。第 2 部には、他のウェブや Mozilla の技術とともに使われる CSS の応用例があります。</p> +<p>第 2 部の各ページで、 CSS とその他の技術を相互作用させる方法を説明します。これらのページは、その他の技術の使い方を学べるようには作られていません。その他の技術の詳細を学ぶなら、他のチュートリアルを探してみてください。</p> +<p>代わりに CSS の数々の用途を解説していきます。読むために CSS の知識が少し必要ですが、その他の技術について何も知っている必要はありません。</p> +<p>前の章(第 1 部): <a href="/ja/docs/CSS/Getting_Started/Media" title="https://developer.mozilla.org/ja/CSS/Getting_Started/Media">メディア</a><br> + 次の章: <a href="/ja/docs/CSS/Getting_Started/SVG_graphics" title="https://developer.mozilla.org/ja/CSS/Getting_Started/SVG_graphics">SVG</a></p> +<h2 id="Information:_JavaScript" name="Information:_JavaScript">JavaScriptについて</h2> +<p>JavaScript は<em>プログラミング言語</em> です。JavaScript はウェブサイトやアプリケーションで、インタラクティブ性を作るのに広く使われています。</p> +<p>JavaScript はスタイルシートと相互に作用でき、文書のスタイルを動的に変えるプログラムを書けます。</p> +<p>3 つの方法があります:</p> +<ul> + <li>文書内のスタイルシートの一覧を扱う方法—例: スタイルシートの追加、削除、編集</li> + <li>スタイルシート内のルールを扱う方法—例: ルールの追加、削除、編集</li> + <li>DOM 内の 個々の要素を扱う方法—文書のスタイルシートと関係なしに、スタイルシートを編集します</li> +</ul> +<table style="border: 1px solid #36b; padding: 1em; background-color: #f4f4f4; margin-bottom: 1em; width: 100%;"> + <caption> + さらに詳しく</caption> + <tbody> + <tr> + <td>JavaScript, についてのさらに詳しい情報は、この wiki の <a href="/ja/docs/JavaScript" title="JavaScript">JavaScript</a> のページをご覧ください。</td> + </tr> + </tbody> +</table> +<h2 id="Action:_A_JavaScript_demonstration" name="Action:_A_JavaScript_demonstration">実習: JavaScript の実演</h2> +<p>新規 HTML 文書 <code>doc5.html</code> を作ってください。以下の内容をコピー&ペーストしてください(スクロールしてすべてをコピーできているか確認してください):</p> +<div style="width: 48em;"> + <pre class="brush:html;"><!DOCTYPE html> +<html> + +<head> +<title>Mozilla CSS Getting Started - JavaScript demonstration</title> +<link rel="stylesheet" type="text/css" href="style5.css" /> +<script type="text/javascript" src="script5.js"></script> +</head> + +<body> +<h1>JavaScript sample</h1> + +<div id="square"></div> + +<button type="button" onclick="doDemo(this);">Click Me</button> + +</body> +</html> +</pre> +</div> +<p>新規 CSS ファイル <code>style5.css</code> を作り、次の内容をコピー&ペーストしてください:</p> +<div style="width: 48em;"> + <pre class="brush:css;">/*** JavaScript demonstration ***/ +#square { + width: 20em; + height: 20em; + border: 2px inset gray; + margin-bottom: 1em; +} + +button { + padding: .5em 2em; +} +</pre> +</div> +<p>新規テキストファイル <code>script5.js</code> を作り、以下の内容をコピー&ペーストしてください:</p> +<div style="width: 48em;"> + <pre class="brush:js;">// JavaScript demonstration +function doDemo (button) { + var square = document.getElementById("square"); + square.style.backgroundColor = "#fa4"; + button.setAttribute("disabled", "true"); + setTimeout(clearDemo, 2000, button); +} + +function clearDemo (button) { + var square = document.getElementById("square"); + square.style.backgroundColor = "transparent"; + button.removeAttribute("disabled"); +} +</pre> +</div> +<p>ブラウザで HTML 文書を開いて、ボタンを押してください。</p> +<p>この wiki はページ内に JavaScript を含められないため、ここで実際の表示をお見せすることはできません。ボタンを押す前と押した後で、結果は次のような感じになるでしょう:</p> +<table> + <tbody> + <tr> + <td style="padding-right: 2em;"> + <table style="border: 2px outset #36b; padding: 0 1em .5em .5em;"> + <tbody> + <tr> + <td> + <p><strong>JavaScript sample</strong></p> + </td> + </tr> + <tr> + <td> </td> + </tr> + </tbody> + </table> + </td> + <td> + <table style="border: 2px outset #36b; padding: 0 1em .5em .5em;"> + <tbody> + <tr> + <td> + <p><strong>JavaScript sample</strong></p> + </td> + </tr> + <tr> + <td style="background: #fa4;"> </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> +</table> +<div class="note"> + この実演についての<strong>重要な補足</strong>: + <ul> + <li>HTML 文書からは、いつものようにスタイルシートがリンクされ、スクリプトもリンクされています</li> + <li>スクリプトは DOM の個々の要素を扱います。正方形のスタイルを直接編集しています。ボタンのスタイルは属性を変更することで、間接的に編集しています。</li> + <li>JavaScript では、<code>document.getElementById("square")</code> は CSS セレクタ <code>#square</code> と、機能的に同義です。</li> + <li>JavaScript では、<code>backgroundColor</code> は CSSのプロパティ <code>background-color</code> に相当します。JavaScriptでは名前にハイフンを含めることができないので、"キャメルケース" が代わりに使われます。</li> + <li>ブラウザ内蔵の CSS ルールには<br> + <code>button{{mediawiki.external('disabled=\"true\"')}}</code> に対するものがあり、ボタンが使用不可にされるとボタンの外見を変更します。</li> + </ul> +</div> +<table style="border: 1px solid #36b; padding: 1em; background-color: #fffff4; margin-bottom: .5em;"> + <caption> + チャレンジ</caption> + <tbody> + <tr> + <td>スクリプトを変更して、色が変わるときに正方形が右に 20 em 跳び、その後元の位置に跳んで戻るようにしてください。</td> + </tr> + </tbody> +</table> +<p><a href="/ja/docs/CSS/Getting_Started/Challenge_solutions#JavaScript" title="https://developer.mozilla.org/ja/CSS/Getting_Started/Challenge_solutions#JavaScript">チャレンジの解答を見る。</a></p> +<h2 id="What_next.3F" name="What_next.3F">さて次は?</h2> +<p>このページにわかりづらいところやご意見があれば <a href="/Talk:ja/CSS/Getting_Started/JavaScript" title="Talk:ja/CSS/Getting_Started/JavaScript">Discussion</a> ページに参加してください。</p> +<p>この実演では、ボタン要素だけがスクリプトを使っているのに、HTML 文書にスクリプトがリンクされていました。Mozilla は CSS を拡張して、JavaScript コード(あるいはコンテンツや他のスタイルシート)を選択した要素にリンクできるようにしています。次のページではこの実演を行います: <strong><a href="/ja/docs/CSS/Getting_Started/XBL_bindings" title="CSS/Getting_Started/XBL_bindings">XBL bindings</a></strong></p> diff --git a/files/ja/conflicting/learn/javascript/objects/index.html b/files/ja/conflicting/learn/javascript/objects/index.html new file mode 100644 index 0000000000..cbe9e10a0a --- /dev/null +++ b/files/ja/conflicting/learn/javascript/objects/index.html @@ -0,0 +1,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> |