Blog
Blog copied to clipboard
[MDN] 私有的類別欄位
私有的類別欄位
- 類別的屬性預設都是公開的, 可以在類別外部修改. 現在可以用 hash
#
前綴在類別欄位上.
語法
class ClassWithPrivateField {
#privateField;
}
class ClassWithPrivateMethod {
#privateMethod() {
return "hello world";
}
}
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD;
}
範例
私有的靜態欄位
- 私有欄位只可以在類別宣告裡面存取.
- 靜態變數只可以被靜態方法呼叫.
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD;
static publicStaticMethod() {
ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42;
return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD;
}
}
console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);
- 私有的靜態欄位在類別求值時, 會加到類別建構子.
- 只有定義私有靜態欄位的類別可以存取.
- 當使用
this
時, 可能導致無法預期的行為.
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);
私有的 instance 欄位
- 私有的 instance 欄位會用 # 名稱 宣告, 前綴
#
.#
是名稱一部分. 用於宣告, 也用於存取.
class ClassWithPrivateField {
#privateField;
constructor() {
this.#privateField = 42;
this.#randomField = 444; // Syntax error
}
}
const instance = new ClassWithPrivateField();
instance.#privateField === 42; // Syntax error
private 方法
private 靜態方法
- 像是公開的一樣, 私有的靜態方法是在類別本身呼叫, 不是類別的 instance. 像是私有的靜態欄位, 他們只能在類別宣告裡面存取.
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);
- 當使用
this
時, 可能導致無法預期的行為. 下方範例中, 當我們試著呼叫Derived.publicStaticMethods()
時,this
參考指向Derived
類別(不是Base
類別), 而上述提到 "只有定義私有靜態欄位的類別可以存取", 所以會失敗.
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
private instance 方法
- 私有的 instance 方法只可以在類別 instance 上使用, 他的存取限制和私有的 instance 欄位相同.
class ClassWithPrivateMethod {
#privateMethod() {
return "hello world";
}
getPrivateMessage() {
return this.#privateMethod();
}
}
const instance = new ClassWithPrivateMethod();
console.log(instance.getPrivateMessage());
// expected output: "hello world"
- 私有的 instance 方法可能是 generate, async 或 async generator 函式. 私有的 getters 和 setters 也可以:
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✨"
瀏覽器相容
- Firefox, IE, Safari, 手持 Firefox Android, iOS Safari, Samsung Internet 都不支援, 其他瀏覽器都支援.