aboutsummaryrefslogtreecommitdiff
path: root/files
diff options
context:
space:
mode:
authorallo <yin199909@aliyun.com>2022-01-14 14:13:32 +0800
committerIrvin <irvinfly@gmail.com>2022-01-19 01:06:50 +0800
commitc5b916c1543ce2023e6df75afa5f9c9d1f483b72 (patch)
treed2200a07e6bac0f12a71c551a45444ef346acda9 /files
parent453c75d5569131fce201fba3fd1849c338ae117e (diff)
downloadtranslated-content-c5b916c1543ce2023e6df75afa5f9c9d1f483b72.tar.gz
translated-content-c5b916c1543ce2023e6df75afa5f9c9d1f483b72.tar.bz2
translated-content-c5b916c1543ce2023e6df75afa5f9c9d1f483b72.zip
sync with english version
Diffstat (limited to 'files')
-rw-r--r--files/zh-cn/web/javascript/reference/classes/private_class_fields/index.md314
1 files changed, 181 insertions, 133 deletions
diff --git a/files/zh-cn/web/javascript/reference/classes/private_class_fields/index.md b/files/zh-cn/web/javascript/reference/classes/private_class_fields/index.md
index 70803df8a1..34074a550a 100644
--- a/files/zh-cn/web/javascript/reference/classes/private_class_fields/index.md
+++ b/files/zh-cn/web/javascript/reference/classes/private_class_fields/index.md
@@ -7,193 +7,241 @@ tags:
- 语言特性
translation_of: Web/JavaScript/Reference/Classes/Private_class_fields
---
-<div>{{JsSidebar("Classes")}}</div>
+{{JsSidebar("Classes")}}
-<p>类属性在默认情况下是公共的,可以被外部类检测或修改。在<a href="https://github.com/tc39/proposal-class-fields">ES2020 实验草案</a> 中,增加了定义私有类字段的能力,写法是使用一个#作为前缀。</p>
+类属性在默认情况下是{{jsxref('Classes/Public_class_fields','公有')}}的,但可以使用增加哈希前缀 `#` 的方法来定义私有类字段,这一隐秘封装的类特性由 JavaScript 自身强制执行。
-<h2 id="语法">语法</h2>
+## 语法
-<pre class="brush: js notranslate">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;
}
-</pre>
-<h2 id="例子"> 例子</h2>
+class ClassWithPrivateStaticMethod {
+ static #privateStaticMethod() {
+ return 'hello world';
+ }
+}
+```
+
+## 示例
+
+### 私有字段
+
+私有字段包括私有实例字段和私有静态字段。
-<h3 id="私有静态字段">私有静态字段</h3>
+#### 私有实例字段
-<p>私有字段可以被类的构造方法(constructor)从内部声明。</p>
+私有实例字段使用 `#名称`(发音为“哈希名称”)声明,这些名称以 `#` 开头。即 `#` 是名称本身的一部分,声明和访问时也需要加上。私有字段在类声明的构造方法中就可被访问。
-<p>静态变量只能被静态方法调用的限制仍然成立。</p>
+从作用域之外引用 `#` 名称、内部在位声明的情况下引用私有字段、或尝试使用 `delete` 移除声明的字段都会抛出语法错误。
-<pre class="brush: js notranslate">class ClassWithPrivateStaticField {
-  static #PRIVATE_STATIC_FIELD
+```js example-bad
+class ClassWithPrivateField {
+ #privateField;
-  static publicStaticMethod() {
-    ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42
-    return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD
-  }
+ constructor() {
+ this.#privateField = 42;
+ delete this.#privateField; // 语法错误
+ this.#undeclaredField = 444; // 语法错误
+ }
}
-assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)</pre>
+const instance = new ClassWithPrivateField()
+instance.#privateField === 42; // 语法错误
+```
+
+> **备注:** 可以使用 [`in`](/zh-CN/docs/Web/JavaScript/Reference/Operators/in) 运算符检查私有字段(或私有方法)是否存在。当私有字段或私有方法存在时,运算符返回 `true`,否则返回 `false`。
-<p>在类评估时,私有静态字段被添加到类构造函数中。</p>
+类似于公有字段,私有字段在构造(construction)基类或调用子类的 `super()` 方法时被添加到类实例中。
-<p>私有静态字段有一个来源限制, 只有定义该私有静态字段的类能访问该字段。</p>
+```js
+class ClassWithPrivateField {
+ #privateField;
-<p>这可能会导致:当使用<strong><code>this</code></strong>时出现意想不到的行为。</p>
+ constructor() {
+ this.#privateField = 42;
+ }
+}
-<pre class="brush: js notranslate">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}
+```
-assertThrows(() =&gt; SubClass.basePublicStaticMethod(), TypeError)
-</pre>
+#### 私有静态字段
-<h3 id="私有实例字段">私有实例字段</h3>
+私有静态字段在解析类结构时被添加到类的构造方法(constructor)中。且静态变量只能被静态方法调用的限制仍然成立。
-<p>私有实例字段使用 <strong>#名称</strong>(发音为“哈希名称”)声明,这些名称以 <code>#</code>开头。  <code>#</code>是名称本身的一部分, 声明和访问时也需要加上。</p>
+```js
+class ClassWithPrivateStaticField {
+ static #PRIVATE_STATIC_FIELD;
+
+ static publicStaticMethod() {
+ ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42;
+ return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD;
+ }
+}
+
+console.log(ClassWithPrivateStaticField.publicStaticMethod() === 42);
+// true
+```
-<p>封装由语言强制执行。 从作用域之外引用#名称是语法错误。</p>
+私有静态字段有一个来源限制:只有定义该私有静态字段的类能访问该字段。使用 **`this`** 可能会出现意想不到的行为。在下方的例子中,`this` 是 `SubClass` 类(而不是 `BaseClassWithPrivateStaticField` 类)的引用,所以尝试调用 `SubClass.basePublicStaticMethod()` 会抛出 `TypeError`。
-<pre class="brush: js notranslate">class ClassWithPrivateField {
-  #privateField
+```js
+class BaseClassWithPrivateStaticField {
+ static #PRIVATE_STATIC_FIELD;
-  constructor() {
-    this.#privateField = 42
-    this.#randomField = 666 // Syntax error
-  }
+ static basePublicStaticMethod() {
+ this.#PRIVATE_STATIC_FIELD = 42;
+ return this.#PRIVATE_STATIC_FIELD;
+ }
}
-const instance = new ClassWithPrivateField()
-instance.#privateField === 42 // Syntax error
-</pre>
+class SubClass extends BaseClassWithPrivateStaticField { };
+
+let error = null;
-<h3 id="私有方法">私有方法</h3>
+try {
+ SubClass.basePublicStaticMethod()
+} catch(e) { error = e};
-<h4 id="私有静态方法">私有静态方法</h4>
+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
+```
-<p>像它们的公有等价方法一样,私有静态方法是在类本身而非类的实例上调用的。 像私有静态字段一样,只能从类声明内部访问它们。</p>
+### 私有方法
-<p>私有静态方法可能是生成器方法,异步方法和异步生成器方法。</p>
+#### 私有实例方法
-<pre class="brush: js notranslate">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();
+ }
}
-assert(ClassWithPrivateStaticField.publicStaticMethod1() === 42);
-assert(ClassWithPrivateStaticField.publicStaticMethod2() === 42);
-</pre>
-
-<p>使用<strong><code>this</code></strong>可能会导致意想不到的行为(因为<code>this</code>绑定规则适用)。</p>
-
-<pre class="brush: js notranslate">class Base {
-    static #privateStaticMethod() {
-        return 42;
-    }
-    static publicStaticMethod1() {
-        return Base.#privateStaticMethod();
-    }
-    static publicStaticMethod2() {
-        return this.#privateStaticMethod();
-    }
+const instance = new ClassWithPrivateMethod();
+console.log(instance.getPrivateMessage());
+// hello world
+```
+
+私有实例方法可以是生成器方法、异步方法或异步生成器方法,也可以是私有的 getter 和 setter。
+
+```js
+class ClassWithPrivateAccessor {
+ #message;
+
+ get #decoratedMessage() {
+ return `🎬${this.#message}🛑`;
+ }
+ set #decoratedMessage(msg) {
+ this.#message = msg;
+ }
+
+ 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
-</pre>
+#### 私有静态方法
-<h4 id="私有实例方法">私有实例方法</h4>
+像它们的公有等价方法一样,私有静态方法是在类本身而非类的实例上调用的。像私有静态字段一样,只能从类声明内部访问它们。
-<p>私有实例方法是类实例上可用的方法,它们的访问方式与私有实例字段相同。</p>
+```js
+class ClassWithPrivateStaticMethod {
+ static #privateStaticMethod() {
+ return 42;
+ }
-<pre class="brush: js notranslate">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"</pre>
+console.log(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42);
+// true
+console.log(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42);
+// true
+```
+
+私有静态方法可以是生成器方法,异步方法或异步生成器方法。
+
+前面提到的私有静态字段的限制同样适用于私有静态方法。同样地,使用 **`this`** 可能会出现意想不到的行为。在下方的例子中,`this` 是 `Derived` 类(而不是 `Base` 类)的引用,所以尝试调用 `Derived.publicStaticMethod2()` 会抛出 `TypeError`。
+
+```js
+class Base {
+ static #privateStaticMethod() {
+ return 42;
+ }
+ static publicStaticMethod1() {
+ return Base.#privateStaticMethod();
+ }
+ static publicStaticMethod2() {
+ return this.#privateStaticMethod();
+ }
+}
-<p>私有实例方法可以是生成器方法,异步方法或异步生成器方法。 私有的getter和setter也是可能的:</p>
+class Derived extends Base {}
-<pre class="brush: js notranslate">class ClassWithPrivateAccessor {
-  #message
+console.log(Derived.publicStaticMethod1());
+// 42
+console.log(Derived.publicStaticMethod2());
+// TypeError: Cannot read private member #privateStaticMethod
+// from an object whose class did not declare it
+```
-  get #decoratedMessage() {
-    return `✨${this.#message}✨`
-  }
-  set #decoratedMessage(msg) {
-    this.#message = msg
-  }
+## 规范
-  constructor() {
-    this.#decoratedMessage = 'hello world'
-    console.log(this.#decoratedMessage)
-  }
-}
+{{Specifications("javascript.classes")}}
-new ClassWithPrivateAccessor();
-// expected output: "✨hello worl​d✨"
-</pre>
-
-<h2 id="规范">规范</h2>
-
-<table class="standard-table">
- <thead>
- <tr>
- <th scope="col">Specification</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}</td>
- </tr>
- </tbody>
-</table>
-
-<h2 id="浏览器兼容性">浏览器兼容性</h2>
-
-<p>{{Compat("javascript.classes.private_class_fields")}}</p>
-
-<h2 id="相关链接">相关链接</h2>
-
-<ul>
- <li><a href="/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields">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>
+## 浏览器兼容性
+
+{{Compat("javascript.classes")}}
+
+## 参见
+
+- [Working with private class features](/en-US/docs/Web/JavaScript/Guide/Working_With_Private_Class_Features)
+- [Public class fields](/zh-CN/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)
+ article at the v8.dev site