做者:Valentino Gagliardijavascript
翻譯:瘋狂的技術宅html
原文:www.valentinog.com/blog/privat…前端
未經容許嚴禁轉載java
在本文中,咱們將對 JavaScript 私有類字段進行一些說明,並瞭解它們與 TypeScript 私有修飾符的區別。git
在過去,JavaScript 沒有保護變量不受訪問的原生機制,固然除非是**典型閉包**。github
閉包是 JavaScript 中許多相似於私有模式(如流行的模塊模式)的基礎。可是,近年來 ECMAScript 2015 類被使用後,開發人員感到須要對類成員的隱私進行更多控制。typescript
類字段提案(在撰寫本文時處於第 3 階段)試圖經過引入 私有類字段 來解決問題。編程
讓咱們看看它們是什麼樣子的。json
這是一個帶有私有字段的 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 是處於 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類的信息:www.typescriptlang.org/docs/handbo…
TypeScript 3.8 私有字段的正式公告:devblogs.microsoft.com/typescript/…