diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/javascript/reference/classes | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/ja/web/javascript/reference/classes')
6 files changed, 1311 insertions, 0 deletions
diff --git a/files/ja/web/javascript/reference/classes/constructor/index.html b/files/ja/web/javascript/reference/classes/constructor/index.html new file mode 100644 index 0000000000..e6fd5e6ddb --- /dev/null +++ b/files/ja/web/javascript/reference/classes/constructor/index.html @@ -0,0 +1,190 @@ +--- +title: コンストラクター +slug: Web/JavaScript/Reference/Classes/constructor +tags: + - Classes + - ECMAScript 2015 + - JavaScript + - Language feature +translation_of: Web/JavaScript/Reference/Classes/constructor +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><span class="seoSummary"><code>constructor</code> メソッドは、 {{jsxref("Statements/class", "class")}} で作成されたオブジェクトの生成と初期化のための特殊なメソッドです。</span></p> + +<div>{{EmbedInteractiveExample("pages/js/classes-constructor.html")}}</div> + +<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div> + +<h2 id="Syntax" name="Syntax">構文</h2> + +<pre class="syntaxbox notranslate">constructor([<var>arguments</var>]) { ... }</pre> + +<h2 id="Description" name="Description">解説</h2> + +<p>コンストラクターを使用すると、インスタンス化されたオブジェクトに対して、他のメソッドを呼び出す前に行う必要のある独自の初期化を提供することができます。</p> + +<pre class="brush: js notranslate">class Person { + + constructor(name) { + this.name = name; + } + + introduce() { + console.log(`Hello, my name is ${this.name}`); + } + +} + +const otto = new Person('Otto'); + +otto.introduce();</pre> + +<p>独自のコンストラクターを提供しなかった場合は、既定のコンストラクターが提供されます。クラスが基底クラスである場合、既定のコンストラクターは空です。</p> + +<pre class="brush: js notranslate">constructor() {}</pre> + +<p>クラスが派生クラスの場合、既定のコンストラクターが親コンストラクターを呼び出し、与えられた引数を渡します。</p> + +<pre class="brush: js notranslate">constructor(...args) { + super(...args); +}</pre> + +<p>それがこのようなコードを動作させることができます。</p> + +<pre class="brush: js notranslate">class ValidationError extends Error { + + printCustomerMessage() { + return `Validation failed :-( (details: ${this.message})`; + } + +} + +try { + throw new ValidationError("Not a valid phone number"); +} catch (error) { + if (error instanceof ValidationError) { + console.log(error.name); // This is Error instead of ValidationError! + console.log(error.printCustomerMessage()); + } else { + console.log('Unknown error', error); + throw error; + } +}</pre> + +<p><code>ValidationError</code> クラスは、独自の初期化を行う必要がないため、明示的なコンストラクターは必要ありません。既定のコンストラクターは、与えられた引数から親の <code>Error</code> の初期化を行います。</p> + +<p>ただし、独自のコンストラクターを提供し、クラスが親クラスから派生している場合は、 <code>super</code> を使用して親クラスのコンストラクターを明示的に呼び出す必要があります。例えば、以下のようになります。</p> + +<pre class="brush: js notranslate">class ValidationError extends Error { + + constructor(message) { + super(message); // call parent class constructor + this.name = 'ValidationError'; + this.code = '42'; + } + + printCustomerMessage() { + return `Validation failed :-( (details: ${this.message}, code: ${this.code})`; + } + +} + +try { + throw new ValidationError("Not a valid phone number"); +} catch (error) { + if (error instanceof ValidationError) { + console.log(error.name); // Now this is ValidationError! + console.log(error.printCustomerMessage()); + } else { + console.log('Unknown error', error); + throw error; + } +} + +</pre> + +<p>クラスには "<code>constructor</code>" という名前の特別なメソッドが 1 つだけ存在します。クラス内に複数の <code>constructor</code> メソッドが存在すると、 {{jsxref("SyntaxError")}} エラーが発生します。</p> + +<h2 id="Examples" name="Examples">例</h2> + +<h3 id="Using_the_constructor_method" name="Using_the_constructor_method">constructor メソッドの使用</h3> + +<p>このコードスニペットは、<a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">classes sample</a> (<a href="https://googlechrome.github.io/samples/classes-es6/index.html">ライブデモ</a>) から転載しています。</p> + +<pre class="brush: js notranslate">class Square extends Polygon { + constructor(length) { + // Here, it calls the parent class' constructor with lengths + // provided for the Polygon's width and height + super(length, length); + // NOTE: In derived classes, `super()` must be called before you + // can use `this`. Leaving this out will cause a ReferenceError. + this.name = 'Square'; + } + + get area() { + return this.height * this.width; + } + + set area(value) { + this.height = value**0.5; + this.width = value**0.5; + } +}</pre> + +<h3 id="Another_example" name="Another_example">他の例</h3> + +<p>ここでは、 <code>Square</code> クラスのプロトタイプが変更されていますが、新しいインスタンスが作成されたときには、その基底クラスである <code>Polygon</code> のコンストラクターが呼び出されます。</p> + +<pre class="brush: js notranslate">class Polygon { + constructor() { + this.name = "Polygon"; + } +} + +class Square extends Polygon { + constructor() { + super(); + } +} + +class Rectangle {} + +Object.setPrototypeOf(Square.prototype, Rectangle.prototype); + +console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false +console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true + +let newInstance = new Square(); +console.log(newInstance.name); //Polygon</pre> + +<h2 id="Specifications" name="Specifications">仕様書</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-static-semantics-constructormethod', 'Constructor Method')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> + +<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div> + +<p>{{Compat("javascript.classes.constructor")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li>{{jsxref("Operators/super", "super()")}}</li> + <li>{{jsxref("Statements/class", "クラス宣言", "", "true")}}</li> + <li>{{jsxref("Operators/class", "クラス式", "", "true")}}</li> + <li>{{jsxref("Classes")}}</li> + <li><a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">Object.prototype.constructor</a></li> +</ul> diff --git a/files/ja/web/javascript/reference/classes/extends/index.html b/files/ja/web/javascript/reference/classes/extends/index.html new file mode 100644 index 0000000000..e4c31b4128 --- /dev/null +++ b/files/ja/web/javascript/reference/classes/extends/index.html @@ -0,0 +1,91 @@ +--- +title: extends +slug: Web/JavaScript/Reference/Classes/extends +tags: + - Classes + - ECMAScript 2015 + - JavaScript + - Language feature +translation_of: Web/JavaScript/Reference/Classes/extends +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><strong><code>extends</code></strong> キーワードは<a href="/ja/docs/Web/JavaScript/Reference/Statements/class">クラス宣言</a>や<a href="/ja/docs/Web/JavaScript/Reference/Operators/class">クラス式</a>の中で、他のクラスの子であるクラスを生成するために使用します。</p> + +<div>{{EmbedInteractiveExample("pages/js/classes-extends.html")}}</div> + +<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div> + +<h2 id="Syntax" name="Syntax">構文</h2> + +<pre class="syntaxbox notranslate">class ChildClass extends ParentClass { ... }</pre> + +<h2 id="Description" name="Description">解説</h2> + +<p><code>extends</code> キーワードは、独自のクラスや組込みオブジェクトをサブクラス化するために使用することができます。</p> + +<p>拡張したものの <code>.prototype</code> は、{{jsxref("Object")}} か {{jsxref("null")}} である必要があります。</p> + +<h2 id="Examples" name="Examples">例</h2> + +<h3 id="Using_extends" name="Using_extends">extends の使用</h3> + +<p>最初の例では、 <code>Square</code> と呼ばれるクラスを <code>Polygon</code> と呼ばれるクラスから作成します。この例は、<a href="https://googlechrome.github.io/samples/classes-es6/index.html">ライブデモ</a> <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">(ソース)</a> から転載しています。</p> + +<pre class="brush: js notranslate">class Square extends Polygon { + constructor(length) { + // ここでは、親クラスのコンストラクターを呼び出し、 + // Polygon の幅と高さの寸法を渡します。 + super(length, length); + // 注: 派生クラスでは、 'this' を使う前に super() を + // 呼び出さなくてはなりません。さもないと参照エラーになります。 + this.name = 'Square'; + } + + get area() { + return this.height * this.width; + } +}</pre> + +<h3 id="Using_extends_with_built-in_objects" name="Using_extends_with_built-in_objects">組込みオブジェクトでの extends の使用</h3> + +<p>この例では、組込みの {{jsxref("Date")}} オブジェクトを拡張します。この例は、<a href="https://googlechrome.github.io/samples/classes-es6/index.html">ライブデモ</a> <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">(ソース)</a> から転載しています。</p> + +<pre class="brush: js notranslate">class myDate extends Date { + + getFormattedDate() { + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + return this.getDate() + '-' + months[this.getMonth()] + '-' + this.getFullYear(); + } +} +</pre> + +<h2 id="Specifications" name="Specifications">仕様書</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'extends')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> + +<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div> + +<p>{{Compat("javascript.classes.extends")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="/ja/docs/Web/JavaScript/Reference/Classes">クラス</a></li> + <li><a href="/ja/docs/Web/JavaScript/Reference/Classes/constructor">コンストラクター</a></li> + <li><a href="/ja/docs/Web/JavaScript/Reference/Operators/super">super</a></li> + <li><a href="https://medium.com/beginners-guide-to-mobile-web-development/super-and-extends-in-javascript-es6-understanding-the-tough-parts-6120372d3420">Anurag Majumdar - Super & Extends in JavaScript</a></li> +</ul> diff --git a/files/ja/web/javascript/reference/classes/index.html b/files/ja/web/javascript/reference/classes/index.html new file mode 100644 index 0000000000..3f711b47ed --- /dev/null +++ b/files/ja/web/javascript/reference/classes/index.html @@ -0,0 +1,424 @@ +--- +title: クラス +slug: Web/JavaScript/Reference/Classes +tags: + - Classes + - Constructors + - ECMAScript 2015 + - Guide + - Inheritance + - Intermediate + - JavaScript +translation_of: Web/JavaScript/Reference/Classes +--- +<div>{{JsSidebar("Classes")}}</div> + +<p>クラスはオブジェクトを作成するためのテンプレートです。それらは、そのデータを処理するためのコードでデータをカプセル化します。JS のクラスはプロトタイプに基づいて構築されていますが、ES5 のクラスライクなセマンティクスとは共有されない構文やセマンティクスも持っています。</p> + +<h2 id="Defining_classes" name="Defining_classes">クラスの定義</h2> + +<p>クラスは実際には「特別な{{jsxref("Functions", "関数", "", "true")}}」であり、{{jsxref("Operators/function", "関数式", "", "true")}}と{{jsxref("Statements/function", "関数宣言", "", "true")}}を定義することができるように、クラス構文にも{{jsxref("Operators/class", "クラス式", "", "true")}}と{{jsxref("Statements/class", "クラス宣言", "", "true")}}の 2 つの定義方法があります。</p> + +<h3 id="Class_declarations" name="Class_declarations">クラス宣言</h3> + +<p>クラスを定義するひとつの方法は、<strong>クラス宣言</strong>を使うことです。クラスを宣言するには、クラス名 (この例では "Rectangle") 付きで <code>class</code> キーワードを使います。</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } +}</pre> + +<h4 id="Hoisting" name="Hoisting">ホイスティング(巻き上げ)</h4> + +<p><strong>関数宣言</strong>と<strong>クラス宣言</strong>の重要な違いは、関数宣言では {{Glossary("Hoisting", "Hoisting")}} されるのに対し、クラス宣言ではされないことです。クラスにアクセスする前に、そのクラスを宣言する必要があります。そうしないと、{{jsxref("ReferenceError")}} が投げられます:</p> + +<pre class="brush: js example-bad notranslate">const p = new Rectangle(); // ReferenceError + +class Rectangle {} +</pre> + +<h3 id="Class_expressions" name="Class_expressions">クラス式</h3> + +<p>クラスを定義する別の方法は<strong>クラス式</strong>です。クラス式は、名前付きでも名前なしでもできます。名前付きクラスの名前は、クラス内のローカルとして扱われます。(ただし (インスタンスのではなく) クラスの {{jsxref("Function.name", "name")}} プロパティによって取得可能)</p> + +<pre class="brush: js notranslate">// 名前なし +let Rectangle = class { + constructor(height, width) { + this.height = height; + this.width = width; + } +}; +console.log(Rectangle.name); +// 出力: "Rectangle" + +// 名前つき +let Rectangle = class Rectangle2 { + constructor(height, width) { + this.height = height; + this.width = width; + } +}; +console.log(Rectangle.name); +// 出力: "Rectangle2" +</pre> + +<div class="note"> +<p><strong>注:</strong> クラス<strong>式</strong>にも{{anch("Class declarations", "クラス宣言")}}で言及したのと同じホイスティング問題があります。</p> +</div> + +<h2 id="Class_body_and_method_definitions" name="Class_body_and_method_definitions">クラス本体とメソッド定義</h2> + +<p>中括弧 <code>{}</code> 内にクラス本体を記述します。クラス本体には、メソッドやコンストラクターといったクラスメンバを記述します。</p> + +<h3 id="Strict_mode" name="Strict_mode">Strict モード</h3> + +<p>クラス本体は <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode">Strict モード</a> で実行されます。つまり、ここで書かれたコードは、パフォーマンスを向上させるために、より厳密な構文に従います。そうでない場合はサイレントエラーが投げられます。なお、特定のキーワードは将来のバージョンの ECMAScript 用に予約されています。</p> + +<h3 id="Constructor" name="Constructor">コンストラクター</h3> + +<p>{{jsxref("Classes/constructor", "コンストラクター", "", "true")}}メソッドは、<code>class</code> で作成したオブジェクトを作成して初期化するための特別なメソッドです。"constructor" という名前の特別なメソッドは、クラスに 1 つしか定義できません。クラスに複数のコンストラクターメソッドが存在する場合、{{jsxref("SyntaxError")}} が投げられます。</p> + +<p>スーパークラスのコンストラクターは <code>super</code> というキーワードで呼び出せます。</p> + +<h3 id="Prototype_methods" name="Prototype_methods">プロトタイプメソッド</h3> + +<p><a href="/ja/docs/Web/JavaScript/Reference/Functions/Method_definitions">メソッド定義</a>を参照してください。</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } + // ゲッター + get area() { + return this.calcArea(); + } + // メソッド + calcArea() { + return this.height * this.width; + } +} + +const square = new Rectangle(10, 10); + +console.log(square.area); // 100</pre> + +<h3 id="Static_methods_and_properties" name="Static_methods_and_properties">静的メソッドとプロパティ</h3> + +<p>{{jsxref("Classes/static", "static", "", "true")}} キーワードは、クラスの静的メソッドまたはプロパティを定義します。静的メンバー(プロパティとメソッド)は、クラスを<a href="/ja/docs/Learn/JavaScript/Objects/Object-oriented_JS#Constructors_and_object_instances">インスタンス化</a>せずに呼び出され、クラスインスタンスを介して呼び出すことは<strong>できません</strong>。静的メソッドは、アプリケーションのユーティリティ関数を作成するためによく使用されますが、静的プロパティは、キャッシュ、固定構成、またはインスタンス間で複製する必要のないその他のデータに役立ちます。</p> + +<pre class="brush: js notranslate">class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + + static displayName = "Point"; + static distance(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; + + return Math.hypot(dx, dy); + } +} + +const p1 = new Point(5, 5); +const p2 = new Point(10, 10); +p1.displayName; // undefined +p1.distance; // undefined +p2.displayName; // undefined +p2.distance; // undefined + +console.log(Point.displayName); // "Point" +console.log(Point.distance(p1, p2)); // 7.0710678118654755 +</pre> + +<h3 id="Boxing_with_prototype_and_static_methods" name="Boxing_with_prototype_and_static_methods">プロトタイプと静的メソッドによるボクシング</h3> + +<p><code>this</code> に値が付けられずに静的メソッドまたはプロトタイプメソッドが呼ばれると、<code>this</code> の値はメソッド内で <code>undefined</code> になります。たとえ <code>"use strict"</code> ディレクティブがなくても同じふるまいになります。なぜなら、<code>class</code> 本体の中のコードは常に Strict モードで実行されるからです。</p> + +<pre class="brush: js notranslate">class Animal { + speak() { + return this; + } + static eat() { + return this; + } +} + +let obj = new Animal(); +obj.speak(); // Animal {} +let speak = obj.speak; +speak(); // undefined + +Animal.eat() // class Animal +let eat = Animal.eat; +eat(); // undefined</pre> + +<p>上のコードを従来の関数ベースの構文を使って書くと、非 Strict モードでは、最初の <code>this</code> の値をもとにして、メソッド呼び出しの中で自動ボクシングが行われます。最初の値が <code>undefined</code> の場合、<code>this</code> にはグローバルオブジェクトが入ります。</p> + +<p>Strict モードでは自動ボクシングは行われません。<code>this</code> の値はそのまま渡されます。</p> + +<pre class="brush: js notranslate">function Animal() { } + +Animal.prototype.speak = function() { + return this; +} + +Animal.eat = function() { + return this; +} + +let obj = new Animal(); +let speak = obj.speak; +speak(); // グローバルオブジェクト(非厳格モード) + +let eat = Animal.eat; +eat(); // グローバルオブジェクト(非厳格モード) +</pre> + +<h3 id="Instance_properties" name="Instance_properties">インスタンスプロパティ</h3> + +<p>インスタンスプロパティはクラスのメソッドの中で定義しなければなりません:</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } +}</pre> + +<p>クラスに付随する静的なプロパティやプロトタイプのプロパティは、クラス本体の宣言の外で定義しなければなりません:</p> + +<pre class="brush: js notranslate">Rectangle.staticWidth = 20; +Rectangle.prototype.prototypeWidth = 25; +</pre> + +<h3 id="Field_declarations" name="Field_declarations">フィールド宣言</h3> + +<div class="warning"> +<p>パブリックフィールドとプライベートフィールドの宣言は JavaScript 標準委員会の <a href="https://tc39.github.io/beta/">TC39</a> で提案されている<a href="https://github.com/tc39/proposal-class-fields">実験的機能(ステージ 3)</a>です。ブラウザーでのサポートは限られていますが、この機能は <a href="https://babeljs.io/">Babel</a> のようなシステムでのビルドステップを通して使用できます。</p> +</div> + +<h4 id="Public_field_declarations" name="Public_field_declarations">パブリックフィールド宣言</h4> + +<p>JavaScript のフィールド宣言構文を使って、上記の例は次のように書くことができます。</p> + +<pre class="brush: js notranslate">class Rectangle { + height = 0; + width; + constructor(height, width) { + this.height = height; + this.width = width; + } +} +</pre> + +<p>フィールドを事前宣言することで、クラス定義はより自己文書化され、フィールドは常に存在するようになります。</p> + +<p>上記のように、フィールドはデフォルト値の有無にかかわらず宣言できます。</p> + +<p>詳しい情報は、{{jsxref("Classes/Public_class_fields", "パブリッククラスフィールド", "", "true")}}を参照してください。</p> + +<h4 id="Private_field_declarations" name="Private_field_declarations">プライベートフィールド宣言</h4> + +<p>プライベートフィールドを使うと、宣言は下記のように洗練できます。</p> + +<pre class="brush: js notranslate">class Rectangle { + #height = 0; + #width; + constructor(height, width) { + this.#height = height; + this.#width = width; + } +} +</pre> + +<p>プライベートフィールドの参照はクラス本体内でのみ可能となり、クラス外からの参照はエラーとなります。クラス外からは見えないものを定義することで、クラスのユーザーが(変更される可能性のある)内部状態に依存できないようにします。</p> + +<div class="note"> +<p>プライベートフィールドは、事前宣言のみ可能です。</p> +</div> + +<p>プライベートフィールドは通常のプロパティとは違い、<code>this</code> への追加によって後から作成することができません。</p> + +<p>詳しい情報は、{{jsxref("Classes/Private_class_fields", "プライベートクラスフィールド", "", "true")}}を参照してください。</p> + +<h2 id="Sub_classing_with_extends" name="Sub_classing_with_extends"><code>extends</code> によるサブクラス</h2> + +<p><code><a href="/ja/docs/Web/JavaScript/Reference/Classes/extends">extends</a></code> キーワードは、クラスを別クラスの子として作成するために、<em>クラス宣言</em>または<em>クラス式</em>の中で使います。</p> + +<pre class="brush: js notranslate">class Animal { + constructor(name) { + this.name = name; + } + + speak() { + console.log(`${this.name} makes a noise.`); + } +} + +class Dog extends Animal { + constructor(name) { + super(name); // スーパークラスのコンストラクターを呼び出し、name パラメータを渡す + } + + speak() { + console.log(`${this.name} barks.`); + } +} + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie barks. +</pre> + +<p>サブクラスにコンストラクターが存在する場合は、"this" を使う前に super() を呼ぶ必要があります。</p> + +<p>従来の関数ベースの「クラス」も拡張できます:</p> + +<pre class="brush: js notranslate">function Animal (name) { + this.name = name; +} + +Animal.prototype.speak = function () { + console.log(`${this.name} makes a noise.`); +} + +class Dog extends Animal { + speak() { + console.log(`${this.name} barks.`); + } +} + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie barks. + +// 同様なメソッドでは、子のメソッドが親のメソッドよりも優先されます。</pre> + +<p>クラスは通常の (生成不可能な) オブジェクトを拡張できないことに注意してください。通常のオブジェクトから継承したければ、代わりに {{jsxref("Object.setPrototypeOf()")}} を使います:</p> + +<pre class="brush: js notranslate">const Animal = { + speak() { + console.log(`${this.name} makes a noise.`); + } +}; + +class Dog { + constructor(name) { + this.name = name; + } +} + +// このコードが無いと、speak() を実行した時に TypeError になります。 +Object.setPrototypeOf(Dog.prototype, Animal); + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie makes a noise. +</pre> + +<h2 id="Species" name="Species">Species</h2> + +<p>Array の派生クラスである <code>MyArray</code> の中で {{jsxref("Array")}} オブジェクトを返したいときもあるでしょう。species パターンは、デフォルトコンストラクタ-を上書きすることができます。</p> + +<p>例えば、デフォルトコンストラクターを返す {{jsxref("Array.map", "map()")}} のようなメソッドを使っているとき、<code>MyArray</code> ではなく <code>Array</code> オブジェクトを返したいでしょう。{{jsxref("Symbol.species")}} シンボルを使うと次のように実現できます。</p> + +<pre class="brush: js notranslate">class MyArray extends Array { + // species を親の Array コンストラクターで上書きする + static get [Symbol.species]() { return Array; } +} + +let a = new MyArray(1,2,3); +let mapped = a.map(x => x * x); + +console.log(mapped instanceof MyArray); // false +console.log(mapped instanceof Array); // true +</pre> + +<h2 id="Super_class_calls_with_super" name="Super_class_calls_with_super"><code>super</code> でスーパークラスを呼び出す</h2> + +<p><code><a href="/ja/docs/Web/JavaScript/Reference/Operators/super">super</a></code> キーワードを使ってスーパークラスのメソッドを呼び出せます。これはプロトタイプベースの継承よりも優れています。</p> + +<pre class="brush: js notranslate">class Cat { + constructor(name) { + this.name = name; + } + + speak() { + console.log(`${this.name} makes a noise.`); + } +} + +class Lion extends Cat { + speak() { + super.speak(); + console.log(`${this.name} roars.`); + } +} + +let l = new Lion('Fuzzy'); +l.speak(); +// Fuzzy makes a noise. +// Fuzzy roars. +</pre> + +<h2 id="Mix-ins" name="Mix-ins">ミックスイン</h2> + +<p>抽象的なサブクラスや<em>ミックスイン</em>はクラスのためのテンプレートです。ECMAScript のクラスは 1 つだけスーパークラスを持つことができます。そのため、多重継承はできません。機能はスーパークラスから提供されます。</p> + +<p>ECMAScript では、スーパークラスをインプットとして、そしてスーパークラスを継承した派生クラスをアウトプットとする関数を mix-in で実装できます:</p> + +<pre class="brush: js notranslate">let calculatorMixin = Base => class extends Base { + calc() { } +}; + +let randomizerMixin = Base => class extends Base { + randomize() { } +}; +</pre> + +<p>ミックスインを使用したクラスを次のように記述することもできます:</p> + +<pre class="brush: js notranslate">class Foo { } +class Bar extends calculatorMixin(randomizerMixin(Foo)) { }</pre> + + +<h2 id="Specifications" name="Specifications">仕様</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">仕様書</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザー実装状況</h2> + + + +<p>{{Compat("javascript.classes")}}</p> + +<h2 id="Re-running_a_class_definition" name="Re-running_a_class_definition">クラス定義の再実行</h2> + +<p>クラスを再定義することはできません。再定義しようとすると <code>SyntaxError</code> が発生します。</p> + +<p>Firefox のウェブコンソール(<strong>メニュー</strong> > <strong>ウェブ開発</strong> > <strong>ウェブコンソール</strong>)などでコードを試しているときに、同じ名前のクラス定義を 2 回実行すると、<code>SyntaxError: redeclaration of let <em>ClassName</em></code> が発生します。(この問題については {{Bug(1428672)}} でさらに詳しく説明しています。)Chrome Developer Tools で同様の操作を行うと、<code>Uncaught SyntaxError: Identifier '<em>ClassName</em>' has already been declared at <anonymous>:1:1</code> のようなメッセージが表示されます。</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li>{{jsxref("Functions", "関数", "", "true")}}</li> + <li>{{jsxref("Statements/class", "クラス宣言", "", "true")}}</li> + <li>{{jsxref("Operators/class", "クラス式", "", "true")}}</li> + <li>{{jsxref("Classes/Public_class_fields", "パブリッククラスフィールド", "", "true")}}</li> + <li>{{jsxref("Classes/Private_class_fields", "プライベートクラスフィールド +", "", "true")}}</li> + <li>{{jsxref("Operators/super", "super")}}</li> + <li><a href="https://hacks.mozilla.org/2015/07/es6-in-depth-classes/">ブログ記事: "ES6 In Depth: Classes"</a></li> + <li><a href="https://github.com/tc39/proposal-class-fields">Fields and public/private class properties proposal (stage 3)</a></li> +</ul> diff --git a/files/ja/web/javascript/reference/classes/private_class_fields/index.html b/files/ja/web/javascript/reference/classes/private_class_fields/index.html new file mode 100644 index 0000000000..6310aa5092 --- /dev/null +++ b/files/ja/web/javascript/reference/classes/private_class_fields/index.html @@ -0,0 +1,207 @@ +--- +title: プライベートクラスフィールド +slug: Web/JavaScript/Reference/Classes/Private_class_fields +tags: + - Classes + - JavaScript + - Language feature +translation_of: Web/JavaScript/Reference/Classes/Private_class_fields +--- +<div>{{JsSidebar("Classes")}}</div> + +<p>クラスのプロパティはデフォルトで公開されており、クラスの外で調べたり変更したりすることができます。しかし、ハッシュ <code>#</code> 接頭辞を使ってプライベートなクラスフィールドを定義できるようにする<a href="https://github.com/tc39/proposal-class-fields">実験的な提案</a>があります。</p> + +<h2 id="Syntax" name="Syntax">構文</h2> + +<pre class="syntaxbox notranslate">class ClassWithPrivateField { + #privateField +} + +class ClassWithPrivateMethod { + #privateMethod() { + return 'hello world' + } +} + +class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD +} +</pre> + +<h2 id="Examples" name="Examples">例</h2> + +<h3 id="Private_static_fields" name="Private_static_fields">プライベートスタティックフィールド</h3> + +<p>プライベートフィールドは、クラスのコンストラクタ上でクラス宣言の内部からアクセスできます。</p> + +<p>静的変数は静的メソッドからのみ呼び出せるという制限はまだあります。</p> + +<pre class="brush: js notranslate">class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static publicStaticMethod() { + ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42 + return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD + } +} + +console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)</pre> + +<p>プライベートスタティックフィールドは、クラスの評価時にクラスのコンストラクタに追加されます。</p> + +<p>プライベートスタティックフィールドには、プライベートスタティックフィールドを定義しているクラスのみが、そのフィールドにアクセスできるという出自制限があります。</p> + +<p>これは、<strong><code>this</code></strong> を使用しているときに予期しない動作をする可能性があります。</p> + +<pre class="brush: js notranslate">class BaseClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static basePublicStaticMethod() { + this.#PRIVATE_STATIC_FIELD = 42 + return this.#PRIVATE_STATIC_FIELD + } +} + +class SubClass extends BaseClassWithPrivateStaticField { } + +let error = null + +try { + SubClass.basePublicStaticMethod() +} catch(e) { error = e} + +console.assert(error instanceof TypeError) +</pre> + +<h3 id="Private_instance_fields" name="Private_instance_fields">プライベートインスタンスフィールド</h3> + +<p>プライベートインスタンスフィールドは <strong># names</strong> (<em>ハッシュネーム</em>) で宣言され、これは <code>#</code> を先頭にした識別子です。この <code>#</code> は名前の一部で、宣言やアクセスにも使われます。</p> + +<p>このカプセル化は言語によって強制されています。範囲外から <code>#</code> の名前を参照するのは構文エラーです。</p> + +<pre class="brush: js notranslate">class ClassWithPrivateField { + #privateField + + constructor() { + this.#privateField = 42 + this.#randomField = 444 // Syntax error + } +} + +const instance = new ClassWithPrivateField() +instance.#privateField === 42 // Syntax error +</pre> + +<h3 id="Private_methods" name="Private_methods">プライベートメソッド</h3> + +<h4 id="Private_static_methods" name="Private_static_methods">プライベートスタティックメソッド</h4> + +<p>プライベートスタティックメソッドは、パブリックと同様に、クラスのインスタンスではなく、クラス自体から呼び出されます。プライベートスタティックフィールドと同様に、クラス宣言の内部からのみアクセス可能です。</p> + +<p>プライベートスタティックメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数、などがあります</p> + +<pre class="brush: js notranslate">class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 42 + } + + static publicStaticMethod1() { + return ClassWithPrivateStaticMethod.#privateStaticMethod(); + } + + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); +console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42); +</pre> + +<p><strong><code>this</code></strong> を使用すると、予期しない動作が発生する可能性があります。次の例では、<code>Derived.publicStaticMethod2()</code> を呼び出そうとしたときに、<code>this</code> が <code>派生</code> クラス(<code>Base</code> クラスではない)を参照しており、上で述べたのと同じ "出自制限" を示します。</p> + +<pre class="brush: js notranslate">class Base { + static #privateStaticMethod() { + return 42; + } + static publicStaticMethod1() { + return Base.#privateStaticMethod(); + } + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +class Derived extends Base {} + +console.log(Derived.publicStaticMethod1()); // 42 +console.log(Derived.publicStaticMethod2()); // TypeError +</pre> + +<h4 id="Private_instance_methods" name="Private_instance_methods">プライベートインスタンスメソッド</h4> + +<p>プライベートインスタンスメソッドは、プライベートインスタンスフィールドと同様にアクセスが制限されているクラスインスタンスで利用できるメソッドです。</p> + +<pre class="brush: js notranslate">class ClassWithPrivateMethod { + #privateMethod() { + return 'hello world' + } + + getPrivateMessage() { + return this.#privateMethod() + } +} + +const instance = new ClassWithPrivateMethod() +console.log(instance.getPrivateMessage()) +// expected output: "hello world"</pre> + +<p>プライベートインスタンスメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数のいずれかになります。プライベートなゲッターやセッターも可能です。</p> + +<pre class="brush: js notranslate">class ClassWithPrivateAccessor { + #message + + get #decoratedMessage() { + return `✨${this.#message}✨` + } + set #decoratedMessage(msg) { + this.#message = msg + } + + constructor() { + this.#decoratedMessage = 'hello world' + console.log(this.#decoratedMessage) + } +} + +new ClassWithPrivateAccessor(); +// expected output: "✨hello world✨" +</pre> + +<h2 id="Specifications" name="Specifications">仕様</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザー実装状況</h2> + + + +<p>{{Compat("javascript.classes.private_class_fields")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="/ja/docs/Web/JavaScript/Reference/Classes/Public_class_fields">パブリッククラスフィールド </a></li> + <li><a href="https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html">The Semantics of All JS Class Elements</a></li> +</ul> diff --git a/files/ja/web/javascript/reference/classes/public_class_fields/index.html b/files/ja/web/javascript/reference/classes/public_class_fields/index.html new file mode 100644 index 0000000000..18614027ce --- /dev/null +++ b/files/ja/web/javascript/reference/classes/public_class_fields/index.html @@ -0,0 +1,267 @@ +--- +title: パブリッククラスフィールド +slug: Web/JavaScript/Reference/Classes/Public_class_fields +tags: + - Classes + - JavaScript + - Language feature +translation_of: Web/JavaScript/Reference/Classes/Public_class_fields +--- +<div>{{JsSidebar("Classes")}}</div> + +<div class="note"> +<p><strong>このページは、実験的な機能について説明しています。</strong></p> + +<p>パブリックフィールド宣言とプライベートフィールド宣言の両方は、JavaScript の標準化委員会である <a href="https://tc39.github.io/beta/">TC39</a> で提案された<a href="https://github.com/tc39/proposal-class-fields">実験的な機能(ステージ 3)</a>です。</p> + +<p>ブラウザーのサポートは限られていますが、<a href="https://babeljs.io/">Babel</a> のようなシステムではビルドステップを経て機能を利用することができます。下記の<a href="#ブラウザーの互換性">互換性情報</a>を参照してください。</p> +</div> + +<p>パブリックスタティックフィールドとパブリックインスタンスフィールドは、書き込み可能、列挙可能、設定可能なプロパティです。そのため、プライベートとは異なり、プロトタイプの継承に参加します。</p> + +<h2 id="Syntax" name="Syntax">構文</h2> + +<pre class="syntaxbox notranslate">class ClassWithInstanceField { + instanceField = 'instance field' +} + +class ClassWithStaticField { + static staticField = 'static field' +} + +class ClassWithPublicInstanceMethod { + publicMethod() { + return 'hello world' + } +} +</pre> + +<h2 id="Examples" name="Examples">例</h2> + +<h3 id="Public_static_fields" name="Public_static_fields">パブリックスタティックフィールド</h3> + +<p>パブリックスタティックフィールドは、すべてのクラスインスタンスを作成するのではなく、クラスごとに一度だけフィールドが存在するようにしたい場合に役立ちます。これは、キャッシュや固定設定、その他インスタンス間で複製する必要のないデータなどに便利です。</p> + +<p>パブリックスタティックフィールドは、<code>static</code> キーワードを使用して宣言されます。これらは、クラスの評価時に{{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} を使用してコンストラクタに追加され、その後はコンストラクタからアクセスします。</p> + +<pre class="brush: js notranslate">class ClassWithStaticField { + static staticField = 'static field' +} + +console.log(ClassWithStaticField.staticField) +// expected output: "static field" +</pre> + +<p>初期化子のないフィールドは <code>undefined</code> に初期化されます。</p> + +<pre class="brush: js notranslate">class ClassWithStaticField { + static staticField +} + +console.assert(ClassWithStaticField.hasOwnProperty('staticField')) +console.log(ClassWithStaticField.staticField) +// expected output: "undefined"</pre> + +<p>パブリックスタティックフィールドはサブクラスを再初期化しませんが、プロトタイプチェーンを介してアクセスすることができます。</p> + +<pre class="brush: js notranslate">class ClassWithStaticField { + static baseStaticField = 'base field' +} + +class SubClassWithStaticField extends ClassWithStaticField { + static subStaticField = 'sub class field' +} + +console.log(SubClassWithStaticField.subStaticField) +// expected output: "sub class field" + +console.log(SubClassWithStaticField.baseStaticField) +// expected output: "base field"</pre> + +<p>フィールドを初期化する場合、<code>this</code> はクラスのコンストラクタを参照します。また、名前で参照し、スーパークラスのコンストラクタが存在する場合は <code>super</code> を使用してスーパークラスのコンストラクタを取得することもできます (存在する場合)。</p> + +<pre class="brush: js notranslate">class ClassWithStaticField { + static baseStaticField = 'base static field' + static anotherBaseStaticField = this.baseStaticField + + static baseStaticMethod() { return 'base static method output' } +} + +class SubClassWithStaticField extends ClassWithStaticField { + static subStaticField = super.baseStaticMethod() +} + +console.log(ClassWithStaticField.anotherBaseStaticField) +// expected output: "base static field" + +console.log(SubClassWithStaticField.subStaticField) +// expected output: "base static method output" +</pre> + +<h3 id="Public_instance_fields" name="Public_instance_fields">パブリックインスタンスフィールド</h3> + +<p>パブリックインスタンスフィールドは、作成されたクラスのすべてのインスタンスに存在します。パブリックフィールドを宣言することで、フィールドが常に存在していることを確認でき、クラスの定義がより自己文書化されます。</p> + +<p>パブリック インスタンスフィールドは、ベースクラスの構築時(コンストラクタ本体が実行される前)、またはサブクラスの <code>super()</code> が返された直後のいずれかに {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} で追加されます。</p> + +<pre class="brush: js notranslate">class ClassWithInstanceField { + instanceField = 'instance field' +} + +const instance = new ClassWithInstanceField() +console.log(instance.instanceField) +// expected output: "instance field"</pre> + +<p>初期化子のないフィールドは <code>undefined</code> に初期化されます。</p> + +<pre class="brush: js notranslate">class ClassWithInstanceField { + instanceField +} + +const instance = new ClassWithInstanceField() +console.assert(instance.hasOwnProperty('instanceField')) +console.log(instance.instanceField) +// expected output: "undefined"</pre> + +<p>プロパティと同様に、フィールド名を計算することができます。</p> + +<pre class="brush: js notranslate">const PREFIX = 'prefix' + +class ClassWithComputedFieldName { + [`${PREFIX}Field`] = 'prefixed field' +} + +const instance = new ClassWithComputedFieldName() +console.log(instance.prefixField) +// expected output: "prefixed field"</pre> + +<p>フィールドを初期化する場合、<code>this</code> は構築中のクラスインスタンスを参照します。パブリックインスタンスメソッドと同じように、サブクラスにいる場合は <code>super</code> を使って superclass プロトタイプにアクセスできます。</p> + +<pre class="brush: js notranslate">class ClassWithInstanceField { + baseInstanceField = 'base field' + anotherBaseInstanceField = this.baseInstanceField + baseInstanceMethod() { return 'base method output' } +} + +class SubClassWithInstanceField extends ClassWithInstanceField { + subInstanceField = super.baseInstanceMethod() +} + +const base = new ClassWithInstanceField() +const sub = new SubClassWithInstanceField() + +console.log(base.anotherBaseInstanceField) +// expected output: "base field" + +console.log(sub.subInstanceField) +// expected output: "base method output"</pre> + +<h3 id="Public_methods" name="Public_methods">パブリックメソッド</h3> + +<h4 id="Public_static_methods" name="Public_static_methods">パブリックスタティックメソッド</h4> + +<p><code><strong>static</strong></code> キーワードは、クラスのスタティックメソッドを定義します。スタティックメソッドは、クラスのインスタンスでは呼び出されません。代わりに、クラス自体から呼び出されます。これらは、オブジェクトを作成したり、クローンを作成したりするユーティリティ関数であることが多いです。</p> + +<pre class="brush: js notranslate">class ClassWithStaticMethod { + static staticMethod() { + return 'static method has been called.'; + } +} + +console.log(ClassWithStaticMethod.staticMethod()); +// expected output: "static method has been called."</pre> + +<p>スタティックメソッドは、クラスの評価時に {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} を使用してクラスのコンストラクタに追加されます。これらのメソッドは書き込み可能、列挙不可、設定可能です。</p> + +<h4 id="Public_instance_methods" name="Public_instance_methods">パブリックインスタンスメソッド</h4> + +<p>パブリックインスタンスメソッドはその名の通り、クラスインスタンスで利用できるメソッドです。</p> + +<pre class="brush: js notranslate">class ClassWithPublicInstanceMethod { + publicMethod() { + return 'hello world' + } +} + +const instance = new ClassWithPublicInstanceMethod() +console.log(instance.publicMethod()) +// expected output: "hello world"</pre> + +<p>パブリックインスタンスメソッドは、{{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} を使用して、クラスの評価時にクラスプロトタイプに追加されます。これらのメソッドは書き込み可能、列挙不可、設定可能です。</p> + +<p>ジェネレーター関数、async、非同期ジェネレーター関数を利用することができます。</p> + +<pre class="brush: js notranslate">class ClassWithFancyMethods { + *generatorMethod() { } + async asyncMethod() { } + async *asyncGeneratorMethod() { } +}</pre> + +<p>インスタンスメソッドの中では、<code>this</code> はインスタンス自体を指します。サブクラスでは、<code>super</code> を使用してスーパークラスのプロトタイプにアクセスし、スーパークラスからメソッドを呼び出すことができます。</p> + +<pre class="brush: js notranslate">class BaseClass { + msg = 'hello world' + basePublicMethod() { + return this.msg + } +} + +class SubClass extends BaseClass { + subPublicMethod() { + return super.basePublicMethod() + } +} + +const instance = new SubClass() +console.log(instance.subPublicMethod()) +// expected output: "hello world" +</pre> + +<p>ゲッターとセッターは、クラスのプロパティにバインドする特別なメソッドで、そのプロパティがアクセスされたり設定されたりしたときに呼び出されます。<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/get">get</a> および <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/set">set</a> 構文を使用して、パブリックインスタンスのゲッターまたはセッターを宣言します。</p> + +<pre class="brush: js notranslate">class ClassWithGetSet { + #msg = 'hello world' + get msg() { + return this.#msg + } + set msg(x) { + this.#msg = `hello ${x}` + } +} + +const instance = new ClassWithGetSet() +console.log(instance.msg) +// expected output: "hello world" + +instance.msg = 'cake' +console.log(instance.msg) +// expected output: "hello cake" +</pre> + +<h2 id="Specifications" name="Specifications">仕様</h2> + + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザー実装状況</h2> + + + +<p>{{Compat("javascript.classes.public_class_fields")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html">The Semantics of All JS Class Elements</a></li> +</ul> diff --git a/files/ja/web/javascript/reference/classes/static/index.html b/files/ja/web/javascript/reference/classes/static/index.html new file mode 100644 index 0000000000..c743df4aff --- /dev/null +++ b/files/ja/web/javascript/reference/classes/static/index.html @@ -0,0 +1,132 @@ +--- +title: static +slug: Web/JavaScript/Reference/Classes/static +tags: + - Classes + - ECMAScript 2015 + - JavaScript + - Language feature + - Static +translation_of: Web/JavaScript/Reference/Classes/static +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><span class="seoSummary"><code><strong>static</strong></code> キーワードは、クラスに静的メソッドや静的プロパティを定義します。静的メソッドも静的プロパティもクラスのインスタンスからは呼び出されません。その代わりに、クラスそのものから呼び出されます。</span>静的メソッドは多くの場合、オブジェクトの生成や複製を行う関数などのユーティリティ関数です。静的プロパティはキャッシュ、固定的な構成、その他の各インスタンスに複製する必要のないデータです。</p> + +<div>{{EmbedInteractiveExample("pages/js/classes-static.html")}}</div> + +<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div> + +<h2 id="Syntax" name="Syntax">構文</h2> + +<pre class="syntaxbox notranslate">static <var>methodName</var>() { ... } +static <var>propertyName </var>[= <var>value</var>]; +</pre> + +<h2 id="Examples" name="Examples">例</h2> + +<h3 id="Using_static_members_in_classes" name="Using_static_members_in_classes">クラスでの静的メンバーの使用</h3> + +<p>次の例はいくつかのことを説明しています。</p> + +<ol> + <li>静的メンバー (メソッドまたはプロパティ) がクラスでどのように定義されるか</li> + <li>静的メンバーを持つクラスがサブクラスを作れるか</li> + <li>静的メンバーがどう呼び出せて、どう呼び出せないか</li> +</ol> + +<pre class="brush: js notranslate">class Triple { + static customName = 'Tripler'; + static description = 'I triple any number you provide'; + static triple(n = 1) { + return n * 3; + } +} + +class BiggerTriple extends Triple { + static longDescription; + static description = 'I square the triple of any number you provide'; + static triple(n) { + return super.triple(n) * super.triple(n); + } +} + +console.log(Triple.description); // 'I triple any number you provide' +console.log(Triple.triple()); // 3 +console.log(Triple.triple(6)); // 18 + +var tp = new Triple(); + +console.log(BiggerTriple.triple(3)); // 81 (not affected by parent's instantiation) +console.log(BiggerTriple.description); // 'I square the triple of any number you provide' +console.log(BiggerTriple.longDescription); // undefined +console.log(BiggerTriple.customName); // 'Tripler' + +console.log(tp.triple()); // 'tp.triple is not a function'. +</pre> + +<h3 id="Calling_static_members_from_another_static_method" name="Calling_static_members_from_another_static_method">静的メンバーの別な静的メソッドからの呼び出し</h3> + +<p>同じクラス内の静的メソッドまたはプロパティを静的メソッドから呼び出すには、 <code><a href="/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code> キーワードを使います。</p> + +<pre class="brush: js notranslate">class StaticMethodCall { + static staticProperty = 'static property'; + static staticMethod() { + return 'Static method and ' + this.staticProperty + ' has been called'; + } + static anotherStaticMethod() { + return this.staticMethod() + ' from another static method'; + } +} +StaticMethodCall.staticMethod(); +// 'Static method and static property has been called' + +StaticMethodCall.anotherStaticMethod(); +// 'Static method and static property has been called from another static method'</pre> + +<h3 id="Calling_static_members_from_a_class_constructor_and_other_methods" name="Calling_static_members_from_a_class_constructor_and_other_methods">クラスのコンストラクターや他のメソッドからの静的メソッドの呼び出し</h3> + +<p>静的メソッドは静的ではないメソッドの {{jsxref("this")}} キーワードを使用して直接アクセスすることができません。呼び出すにはクラス名を使用して <code>クラス名.静的メソッド名()</code> / <code>クラス名.静的プロパティ名</code> のようにするか、 <code>constructor</code> プロパティのメソッドとして <code>this.constructor.静的メソッド名() </code> / <code>this.constructor.静的プロパティ名</code> のようにしてください。</p> + +<pre class="brush: js notranslate">class StaticMethodCall { + constructor() { + console.log(StaticMethodCall.staticProperty); // 'static property' + console.log(this.constructor.staticProperty); // 'static property' + console.log(StaticMethodCall.staticMethod()); // 'static method has been called.' + console.log(this.constructor.staticMethod()); // 'static method has been called.' + } + + static staticProperty = 'static property'; + static staticMethod() { + return 'static method has been called.'; + } +}</pre> + +<h2 id="Specifications" name="Specifications">仕様書</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> + +<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div> + +<p>{{Compat("javascript.classes.static")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="/ja/docs/Web/JavaScript/Reference/Operators/class"><code>class</code> 式</a></li> + <li><a href="/ja/docs/Web/JavaScript/Reference/Statements/class"><code>class</code> 宣言</a></li> + <li><a href="/ja/docs/Web/JavaScript/Reference/Classes">クラス</a></li> +</ul> |