Blog icon indicating copy to clipboard operation
Blog copied to clipboard

[MDN] 私有的類別欄位

Open ChaoLiou opened this issue 4 years ago • 0 comments

私有的類別欄位

  • 類別的屬性預設都是公開的, 可以在類別外部修改. 現在可以用 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 都不支援, 其他瀏覽器都支援.

ChaoLiou avatar Jan 28 '21 03:01 ChaoLiou