From bd8d5d8d15769e49b0720efdb8c76a2840d2cec7 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Wed, 22 Sep 2021 02:18:51 +0900 Subject: Classes/Private_class_fields を更新 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Markdown へ変換 - 2021/07/21 時点の英語版に同期 --- .../classes/private_class_fields/index.md | 272 ++++++++++++--------- 1 file changed, 155 insertions(+), 117 deletions(-) (limited to 'files/ja/web/javascript/reference') diff --git a/files/ja/web/javascript/reference/classes/private_class_fields/index.md b/files/ja/web/javascript/reference/classes/private_class_fields/index.md index 6310aa5092..dfb19fd13f 100644 --- a/files/ja/web/javascript/reference/classes/private_class_fields/index.md +++ b/files/ja/web/javascript/reference/classes/private_class_fields/index.md @@ -1,207 +1,245 @@ --- -title: プライベートクラスフィールド +title: プライベートクラス機能 slug: Web/JavaScript/Reference/Classes/Private_class_fields tags: - Classes + - Private - JavaScript - Language feature translation_of: Web/JavaScript/Reference/Classes/Private_class_fields --- -
{{JsSidebar("Classes")}}
+{{JsSidebar("Classes")}} -

クラスのプロパティはデフォルトで公開されており、クラスの外で調べたり変更したりすることができます。しかし、ハッシュ # 接頭辞を使ってプライベートなクラスフィールドを定義できるようにする実験的な提案があります。

+クラスのフィールドは既定で{{ jsxref('Classes/Public_class_fields','公開', '', 1) }}ですが、ハッシュ `#` 接頭辞を使ってプライベートクラスメンバーを生成することができます。これらのクラス機能のプライバシーのカプセル化は、JavaScript 自身によって行われます。 -

構文

+## 構文 -
class ClassWithPrivateField {
-  #privateField
+```js
+class ClassWithPrivateField {
+  #privateField;
 }
 
 class ClassWithPrivateMethod {
   #privateMethod() {
-    return 'hello world'
+    return 'hello world';
   }
 }
 
 class ClassWithPrivateStaticField {
-  static #PRIVATE_STATIC_FIELD
+  static #PRIVATE_STATIC_FIELD;
 }
-
-

+class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 'hello world'; + } +} +``` -

プライベートスタティックフィールド

+## 例 -

プライベートフィールドは、クラスのコンストラクタ上でクラス宣言の内部からアクセスできます。

+### プライベートインスタンスフィールド -

静的変数は静的メソッドからのみ呼び出せるという制限はまだあります。

+プライベートインスタンスフィールドは **# 名** (*ハッシュ名*と読む) で宣言され、これは `#` の接頭辞が付いた識別子です。この `#` は名前の一部で、宣言やアクセスにも使われます。プライベートフィールドはクラスのコンストラクターー上でクラス定義自身の中から参照できます。フィールド名の宣言や、フィールドの値へのアクセスに使用されます。 -
class ClassWithPrivateStaticField {
-  static #PRIVATE_STATIC_FIELD
+スコープ外から `#` 名を参照すると構文エラーになります。また、呼び出される前に宣言されていないプライベートフィールドを参照したり、宣言されているフィールドを `delete` で削除しようとしても構文エラーになります。
 
-  static publicStaticMethod() {
-    ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42
-    return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD
+```js example-bad
+class ClassWithPrivateField {
+  #privateField;
+
+  constructor() {
+    this.#privateField = 42;
+    delete this.#privateField;   // Syntax error
+    this.#undeclaredField = 444; // Syntax error
   }
 }
 
-console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)
+const instance = new ClassWithPrivateField() +instance.#privateField === 42; // Syntax error +``` + +> **Note:** [`in`](/ja/docs/Web/JavaScript/Reference/Operators/in) 演算子を使用すると、プライベートフィールド (またはプライベートメソッド) が欠けているかどうかをチェックできます。そのプライベートフィールドが存在すれば `true` を返し、そうでなければ `false` を返します。 -

プライベートスタティックフィールドは、クラスの評価時にクラスのコンストラクタに追加されます。

+パブリックフィールドのように、プライベートフィールドは基底クラスの構築辞典、またはサブクラス内で `super()` が呼び出される場面で追加されます。 -

プライベートスタティックフィールドには、プライベートスタティックフィールドを定義しているクラスのみが、そのフィールドにアクセスできるという出自制限があります。

+```js +class ClassWithPrivateField { + #privateField; -

これは、this を使用しているときに予期しない動作をする可能性があります。

+ constructor() { + this.#privateField = 42; + } +} -
class BaseClassWithPrivateStaticField {
-  static #PRIVATE_STATIC_FIELD
+class SubClass extends ClassWithPrivateField {
+  #subPrivateField;
 
-  static basePublicStaticMethod() {
-    this.#PRIVATE_STATIC_FIELD = 42
-    return this.#PRIVATE_STATIC_FIELD
+  constructor() {
+    super();
+    this.#subPrivateField = 23;
   }
 }
 
-class SubClass extends BaseClassWithPrivateStaticField { }
+new SubClass();
+// SubClass {#privateField: 42, #subPrivateField: 23}
+```
 
-let error = null
+### プライベート静的フィールド
 
-try {
-  SubClass.basePublicStaticMethod()
-} catch(e) { error = e}
+プライベートフィールドは、クラスのコンストラクター上でクラス宣言の内部からアクセスできます。
+静的変数は静的メソッドからのみ呼び出せるという制限はまだあります。
 
-console.assert(error instanceof TypeError)
-
+```js +class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD; -

プライベートインスタンスフィールド

+ static publicStaticMethod() { + ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42; + return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD; + } +} -

プライベートインスタンスフィールドは # names (ハッシュネーム) で宣言され、これは # を先頭にした識別子です。この # は名前の一部で、宣言やアクセスにも使われます。

+console.log(ClassWithPrivateStaticField.publicStaticMethod() === 42); +// true +``` -

このカプセル化は言語によって強制されています。範囲外から # の名前を参照するのは構文エラーです。

+プライベート静的フィールドには制限があります。プライベート静的フィールドを定義したクラスのみが、そのフィールドにアクセスできます。**`this`** を使用すると、予期しない動作をする可能性があります。 +次の例では、`SubClass.basePublicStaticMethod()` を呼び出そうとしたときに、これが (`BaseClassWithPrivateStaticField` クラスではなく) `SubClass` クラスを参照してしまい、 `TypeError` が発生します。 -
class ClassWithPrivateField {
-  #privateField
+```js
+class BaseClassWithPrivateStaticField {
+  static #PRIVATE_STATIC_FIELD;
 
-  constructor() {
-    this.#privateField = 42
-    this.#randomField = 444 // Syntax error
+  static basePublicStaticMethod() {
+    this.#PRIVATE_STATIC_FIELD = 42;
+    return this.#PRIVATE_STATIC_FIELD;
   }
 }
 
-const instance = new ClassWithPrivateField()
-instance.#privateField === 42 // Syntax error
-
+class SubClass extends BaseClassWithPrivateStaticField { }; -

プライベートメソッド

+let error = null; -

プライベートスタティックメソッド

+try { + SubClass.basePublicStaticMethod() +} catch(e) { error = e}; -

プライベートスタティックメソッドは、パブリックと同様に、クラスのインスタンスではなく、クラス自体から呼び出されます。プライベートスタティックフィールドと同様に、クラス宣言の内部からのみアクセス可能です。

+console.log(error instanceof TypeError); +// true +console.log(error); +// TypeError: Cannot write private member #PRIVATE_STATIC_FIELD +// to an object whose class did not declare it +``` -

プライベートスタティックメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数、などがあります

+### プライベートメソッド -
class ClassWithPrivateStaticMethod {
-  static #privateStaticMethod() {
-    return 42
-  }
+#### プライベートインスタンスメソッド
 
-  static publicStaticMethod1() {
-    return ClassWithPrivateStaticMethod.#privateStaticMethod();
+プライベートインスタンスメソッドは、プライベートインスタンスフィールドと同様にアクセスが制限されているクラスインスタンスで利用できるメソッドです。
+
+```js
+class ClassWithPrivateMethod {
+  #privateMethod() {
+    return 'hello world';
   }
 
-  static publicStaticMethod2() {
-    return this.#privateStaticMethod();
+  getPrivateMessage() {
+    return this.#privateMethod();
   }
 }
 
-console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42);
-console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42);
-
+const instance = new ClassWithPrivateMethod(); +console.log(instance.getPrivateMessage()); +// hello world +``` -

this を使用すると、予期しない動作が発生する可能性があります。次の例では、Derived.publicStaticMethod2() を呼び出そうとしたときに、this派生 クラス(Base クラスではない)を参照しており、上で述べたのと同じ "出自制限" を示します。

+プライベートインスタンスメソッドは、ジェネレーター関数、非同期関数、非同期ジェネレーター関数のいずれかになります。プライベートなゲッターやセッターも可能です。 -
class Base {
-  static #privateStaticMethod() {
-    return 42;
+```js
+class ClassWithPrivateAccessor {
+  #message;
+
+  get #decoratedMessage() {
+    return `🎬${this.#message}🛑`;
   }
-  static publicStaticMethod1() {
-    return Base.#privateStaticMethod();
+  set #decoratedMessage(msg) {
+    this.#message = msg;
   }
-  static publicStaticMethod2() {
-    return this.#privateStaticMethod();
+
+  constructor() {
+    this.#decoratedMessage = 'hello world';
+    console.log(this.#decoratedMessage);
   }
 }
 
-class Derived extends Base {}
+new ClassWithPrivateAccessor();
+// 🎬hello world🛑
+```
 
-console.log(Derived.publicStaticMethod1()); // 42
-console.log(Derived.publicStaticMethod2()); // TypeError
-
+#### プライベート静的メソッド -

プライベートインスタンスメソッド

+プライベート静的メソッドは、パブリックと同様に、クラスのインスタンスではなく、クラス自体から呼び出されます。プライベート静的フィールドと同様に、クラス宣言の内部からのみアクセス可能です。 -

プライベートインスタンスメソッドは、プライベートインスタンスフィールドと同様にアクセスが制限されているクラスインスタンスで利用できるメソッドです。

+```js +class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 42; + } -
class ClassWithPrivateMethod {
-  #privateMethod() {
-    return 'hello world'
+  static publicStaticMethod1() {
+    return ClassWithPrivateStaticMethod.#privateStaticMethod();
   }
 
-  getPrivateMessage() {
-    return this.#privateMethod()
+  static publicStaticMethod2() {
+    return this.#privateStaticMethod();
   }
 }
 
-const instance = new ClassWithPrivateMethod()
-console.log(instance.getPrivateMessage())
-// expected output: "hello worl​d"
+console.log(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); +// true +console.log(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42); +// true +``` -

プライベートインスタンスメソッドは、ジェネレーター関数、async、非同期ジェネレーター関数のいずれかになります。プライベートなゲッターやセッターも可能です。

+プライベート静的メソッドは、ジェネレーター関数、非同期関数、非同期ジェネレーター関数、などがあります。 -
class ClassWithPrivateAccessor {
-  #message
+前述のプライベート静的フィールドの制限は、プライベート静的メソッドにも当てはまり、**`this`** を同様に使用すると予期しない動作が発生する可能性があります。次の例では、 `Derived.publicStaticMethod2()` を呼び出そうとすると、これは `Base` クラスではなく `Derived` クラスを参照するため、`TypeError` が発生します。
 
-  get #decoratedMessage() {
-    return `✨${this.#message}✨`
+```js
+class Base {
+  static #privateStaticMethod() {
+    return 42;
   }
-  set #decoratedMessage(msg) {
-    this.#message = msg
+  static publicStaticMethod1() {
+    return Base.#privateStaticMethod();
   }
-
-  constructor() {
-    this.#decoratedMessage = 'hello world'
-    console.log(this.#decoratedMessage)
+  static publicStaticMethod2() {
+    return this.#privateStaticMethod();
   }
 }
 
-new ClassWithPrivateAccessor();
-// expected output: "✨hello worl​d✨"
-
- -

仕様

+class Derived extends Base {} - - - - - - - - - - - -
仕様書
{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}
+console.log(Derived.publicStaticMethod1()); +// 42 +console.log(Derived.publicStaticMethod2()); +// TypeError: Cannot read private member #privateStaticMethod +// from an object whose class did not declare it +``` -

ブラウザー実装状況

+## 仕様書 +{{Specifications("javascript.classes")}} +## ブラウザーの互換性 -

{{Compat("javascript.classes.private_class_fields")}}

+{{Compat("javascript.classes")}} -

関連情報

+## 関連情報 - +- [プライベートクラス機能での作業](/ja/docs/Web/JavaScript/Guide/Working_With_Private_Class_Features) +- [パブリッククラスフィールド](/ja/docs/Web/JavaScript/Reference/Classes/Public_class_fields) +- [The Semantics of All JS Class Elements](https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html) +- [Public and private class fields](https://v8.dev/features/class-fields) + v8.dev サイトの記事 -- cgit v1.2.3-54-g00ecf