JavaScript 私有類字段和 TypeScript 私有修飾符

做者:Valentino Gagliardijavascript

翻譯:瘋狂的技術宅html

原文:www.valentinog.com/blog/privat…前端

未經容許嚴禁轉載java

在本文中,咱們將對 JavaScript 私有類字段進行一些說明,並瞭解它們與 TypeScript 私有修飾符的區別。git

JavaScript private class fields and the TypeScript private modifier

JavaScript 私有類字段和隱私需求

在過去,JavaScript 沒有保護變量不受訪問的原生機制,固然除非是**典型閉包**。github

閉包是 JavaScript 中許多相似於私有模式(如流行的模塊模式)的基礎。可是,近年來 ECMAScript 2015 類被使用後,開發人員感到須要對類成員的隱私進行更多控制typescript

類字段提案(在撰寫本文時處於第 3 階段)試圖經過引入 私有類字段 來解決問題。編程

讓咱們看看它們是什麼樣子的。json

一個 JavaScript 私有類字段的例子

這是一個帶有私有字段的 JavaScript 類,請注意,與「公有」成員不一樣,每一個私有字段必須在訪問前進行聲明前端工程化

class Person {
  #age;
  #name;
  #surname;
  constructor(name, surname, age) {
    this.#name = name;
    this.#surname = surname;
    this.#age = age;
  }
  getFullName() {
    return `${this.#name} + ${this.#surname}`;
  }
}
複製代碼

沒法從類的外部訪問私有類字段

class Person {
  #age;
  #name;
  #surname;
  constructor(name, surname, age) {
    this.#name = name;
    this.#surname = surname;
    this.#age = age;
  }
  getFullName() {
    return `${this.#name} + ${this.#surname}`;
  }
}
const marta = new Person("Marta", "Cantrell", 33);
console.log(marta.#age); // SyntaxError
複製代碼

這是真正的「隱私」。若是你會一點 TypeScript,可能會問「原生」私有字段與 TypeScript 中的 private 修飾符 有什麼共同點。

好吧,答案是:沒有。可是爲何?

TypeScript 中的 private 修飾符

有着傳統編程語言背景的開發人員應該熟悉 TypeScript 中的 private 修飾符。簡而言之,此關鍵字的目的是拒絕從類的外部訪問類成員。

可是請不要忘記,TypeScript 是處於 JavaScript 之上的一層,而且 TypeScript 編譯器應該剝離全部花裏胡哨的 TypeScript 註釋,包括 private

這意味着下面的類作不到你想要的工做:

class Person {
  private age: number;
  private name: string;
  private surname: string;
  constructor(name: string, surname: string, age: number) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }
  getFullName() {
    return `${this.name} + ${this.surname}`;
  }
}
const liz = new Person("Liz", "Cantrill", 31);
// @ts-ignore
console.log(liz.age);
複製代碼

若是沒有 //@ts-ignore,在訪問 liz.age僅會在 TypeScript 中引起錯誤,可是在編譯以後,你將會獲得下面的 JavaScript 代碼:

"use strict";
var Person = /** @class */ (function () {
    function Person(name, surname, age) {
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
    Person.prototype.getFullName = function () {
        return this.name + " + " + this.surname;
    };
    return Person;
}());
var liz = new Person("Liz", "Cantrill", 31);
console.log(liz.age); // 31
複製代碼

與預期的同樣,咱們能夠從控制檯輸出 liz.age這裏的主要觀點是 TypeScript 中的 private 不是那麼私有,而且僅在 TypeScript 級別才感到方便,而不是「真正的隱私」。

接下來咱們開始討論:TypeScript 中的「原生」私有類字段

TypeScript 中的私有類字段

TypeScript 3.8 將支持 ECMAScript 私有字段,千萬別和 TypeScript private 修飾符 混淆。

這是在 TypeScript 中具備私有類字段的類:

class Person {
    #age: number;
    #name: string;
    #surname: string;
    constructor(name:string, surname:string, age:number) {
        this.#name = name;
        this.#surname = surname;
        this.#age = age;
    }
    getFullName() {
        return `${this.#name} + ${this.#surname}`;
    }
}
複製代碼

除了類型註釋外,與原生 JavaScript 沒什麼不一樣。沒法從外部訪問成員。可是 TypeScript 中私有字段的真正問題在於它們在後臺使用了 WeakMap

要編譯此代碼,咱們須要調整 tsconfig.json 中的目標編譯版本,該版本最低必須是 ECMAScript 2015

{
  "compilerOptions": {
    "target": "es2015",
    "strict": true,
    "lib": ["dom","es2015"]
  }
}
複製代碼

這可能會出現問題,具體取決於目標瀏覽器,除非你打算爲 WeakMap 提供 polyfill,不然,若是隻是爲了編寫精美的新語法,工做量就變得太多了。

JavaScript 中老是存在這種緊張關係,你確實想使用新語法,但另外一方面,你不想因爲大量的 polyfill 影響使用戶體驗。

另外一方面,即便你但願將其發佈到較新的瀏覽器中,也沒必要擔憂私有類字段。最起碼如今是這樣。甚至Firefox都沒有實施該建議。

結論

在撰寫本文時它還是一項提案,JavaScript 類字段頗有趣,可是瀏覽器供應商的支持不好。 那麼你對此功能有何見解

這是個人:

  • 我喜歡 ES 私有類字段(儘管我不喜歡 #
  • 在 TypeScript 中從不依賴 private, 這僅在 TS 級別是有用的
  • 我會等待瀏覽器提供私有類字段
  • 我目前不會在 TS 中使用私有類字段

瞭解更多有關TypeScript類的信息:www.typescriptlang.org/docs/handbo…

TypeScript 3.8 私有字段的正式公告:devblogs.microsoft.com/typescript/…

歡迎關注前端公衆號:前端先鋒,免費領取前端工程化實用工具包。

相關文章
相關標籤/搜索