做者:Valentino Gagliardi翻譯:瘋狂的技術宅javascript
原文:https://www.valentinog.com/bl...html
未經容許嚴禁轉載前端
在本文中,咱們將對 JavaScript 私有類字段進行一些說明,並瞭解它們與 TypeScript 私有修飾符的區別。java
在過去,JavaScript 沒有保護變量不受訪問的原生機制,固然除非是典型閉包。git
閉包是 JavaScript 中許多相似於私有模式(如流行的模塊模式)的基礎。可是,近年來 ECMAScript 2015 類被使用後,開發人員感到須要對類成員的隱私進行更多控制。程序員
類字段提案(在撰寫本文時處於第 3 階段)試圖經過引入 私有類字段 來解決問題。github
讓咱們看看它們是什麼樣子的。面試
這是一個帶有私有字段的 JavaScript 類,請注意,與「公有」成員不一樣,每一個私有字段必須在訪問前進行聲明:typescript
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 是處於 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 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 類字段頗有趣,可是瀏覽器供應商的支持不好。 那麼你對此功能有何見解?
這是個人:
#
)瞭解更多有關TypeScript類的信息:https://www.typescriptlang.or...
TypeScript 3.8 私有字段的正式公告:https://devblogs.microsoft.co...