詳解JavaScript 新語法之Class 的私有屬性與私有方法
譯者按: 為什么偏要用 # 符號(hào)?
原文:JavaScript's new #private class fields
•譯者:Fundebug
本文采用意譯,版權(quán)歸原作者所有
proposal-class-fields與proposal-private-methods定義了 Class 的私有屬性以及私有方法,這 2 個(gè)提案已經(jīng)處于 Stage 3,這就意味著它們已經(jīng)基本確定下來了,等待被加入到新的 ECMAScript 版本中。事實(shí)上,最新的 Chrome 已經(jīng)支持了 Class 私有屬性。
那么,對(duì)于 Class 的私有屬性與私有方法,它們究竟是什么呢?它們是怎樣工作的?為什么要使用#符號(hào)來定義呢?
Class 的私有屬性語法如下:
class Point {
#x;
#y;
constructor(x, y) {
this.#x = x;
this.#y = y;
}
equals(point) {
return this.#x === point.#x && this.#y === point.#y;
}
}
我們可以將其語法理解為 2 個(gè)部分:
•定義 Class 私有屬性
•引用 Class 私有屬性
定義 Class 私有屬性
私有屬性與公共屬性的定義方式幾乎是一樣的,只是需要在屬性名稱前面添加#符號(hào):
class Foo {
publicFieldName = 1;
#privateFieldName = 2;
}
定義私有屬性的時(shí)候也可以不用賦值:
class Foo {
#privateFieldName;
}
引用 Class 私有屬性
引用私有屬性也只需要使用#就好了。
class Foo {
publicFieldName = 1;
#privateFieldName = 2;
add() {
return this.publicFieldName + this.#privateFieldName;
}
}
其中,this.#可以簡(jiǎn)化,去掉 this 也沒問題,下面兩種寫法是等價(jià)的:
method() {
#privateFieldName;
}
method() {
this.#privateFieldName;
}
在 Class 定義中引用 Class 實(shí)例的私有屬性
對(duì)于私有屬性,我們是不可以直接通過 Class 實(shí)例來引用的,這也是私有屬性的本來含義。但是有一種情況除外,在 Class 定義中,我們可以引用 Class 實(shí)例的私有屬性:
class Foo {
#privateValue = 42;
static getPrivateValue(foo) {
return foo.#privateValue;
}
}
Foo.getPrivateValue(new Foo()); // >> 42
其中,foo是Foo的實(shí)例,在 Class 定義中,我們可以通過 foo 來引用私有屬性#privateValue。
Class 的私有方法
Class 的私有屬性是提案proposal-class-fields的一部分,這個(gè)提案只關(guān)注 Class 的屬性,它并沒有對(duì) Class 的方法進(jìn)行任何修改。而 Class 的私有方法是提案proposal-class-fields的一部分。
Class 的私有方法語法如下:
class Foo {
constructor() {
this.#method();
}
#method() {
// ...
}
}
我們也可以將函數(shù)賦值給私有屬性:
class Foo {
constructor() {
this.#method();
}
#method = () => {
// ...
};
}
封裝(隱藏)私有屬性
我們不能直接通過 Class 實(shí)例引用私有屬性,我們只能在 Class 定義中引用它們:
class Foo {
#bar;
method() {
this.#bar; // Works
}
}
let foo = new Foo();
foo.#bar; // Invalid!
另外,要做到真正的私有的話,我們應(yīng)該無法檢測(cè)這個(gè)私有屬性是否存在,因此,我們需要允許定義同名的公共屬性:
class Foo {
bar = 1; // public bar
#bar = 2; // private bar
}
如果我們不允許公共屬性與私有屬性同名,我們則可以通過給同名的公共屬性復(fù)制監(jiān)測(cè)該私有屬性是否存在:
foo.bar = 1; // Error: `bar` is private! (報(bào)錯(cuò),說明私有屬性存在)
不報(bào)錯(cuò)也行:
foo.bar = 1; foo.bar; // `undefined` (賦值失敗,說明私有屬性存在)
對(duì)于 subclass 應(yīng)該同樣如此,它也允許公共屬性與私有屬性同名:
class Foo {
#fieldName = 1;
}
class Bar extends Foo {
fieldName = 2; // Works!
}
關(guān)于 Class 私有屬性的封裝,可以參考Why is encapsulation a goal of this proposal?。
為什么使用#符號(hào)?
很多人都有一個(gè)疑問,為什么 JS 不能學(xué)習(xí)其他語言,使用private來定義私有屬性和私有方法?為什么要使用奇怪的#符號(hào)?
使用 private 的話,代碼要舒服很多:
class Foo {
private value;
equals(foo) {
return this.value === foo.value;
}
}
為什么不使用 private 來定義私有屬性?
很多語言使用 private 來定義私用屬性,如下:
class EnterpriseFoo {
public bar;
private baz;
method() {
this.bar;
this.baz;
}
}
對(duì)于這些語言屬性,私用屬性和公共屬性的引用方式是相同的,因此他們可以使用 private 來定義私有屬性。
但是,對(duì)于 JavaScript 來說,我們不能使用 this.field 來引用私有屬性(我接下來會(huì)解釋原因),我們需要在語法層面上區(qū)分私有屬性和公共屬性。在定義和引用私有屬性的時(shí)候,使用#符號(hào),私有屬性與公共屬性可以很好地區(qū)分開來。
為什么引用私有屬性的時(shí)候需要#符號(hào)?
引用私有屬性的時(shí)候,我們需要this.#field,而不是this.field,原因如下:
•因?yàn)槲覀冃枰庋b私有屬性,我們需要允許公共屬性與私有屬性同名,因此私有屬性與公共屬性的引用方式必須不一樣。這一點(diǎn)我們?cè)谇拔囊呀?jīng)詳述。
•公共屬性可以通過this.field以及this['field']來引用,但是私有屬性不能支持this['field']這種方式,否則會(huì)破壞私有屬性的隱私性,示例如下:
class Dict extends null {
#data = something_secret;
add(key, value) {
this[key] = value;
}
get(key) {
return this[key];
}
}
new Dict().get("#data"); // 返回私有屬性
因此,私有屬性與公共屬性的引用方式必須不一樣,否則會(huì)破壞this['field']語法。
•私有屬性與公共屬性的引用方式一樣的話,會(huì)導(dǎo)致我們每次都需要去檢查屬性是公共的還是私有的,這會(huì)造成嚴(yán)重的性能問題。
這篇文章遵循Creative Commons Attribution 4.0 International License。
參考
•Why is encapsulation a goal of this proposal?
總結(jié)
以上所述是小編給大家介紹的JavaScript 新語法之Class 的私有屬性與私有方法,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- 溫習(xí)Javascript基礎(chǔ)語法之詞法結(jié)構(gòu)
- JavaScript語法約定和程序調(diào)試原理解析
- javascript中正則表達(dá)式語法詳解
- javascript 高級(jí)語法之繼承的基本使用方法示例
- JSON基本語法及與JavaScript的異同實(shí)例分析
- NodeJS模塊與ES6模塊系統(tǒng)語法及注意點(diǎn)詳解
- JavaScript ES6中的簡(jiǎn)寫語法總結(jié)與使用技巧
- js es6系列教程 - 新的類語法實(shí)戰(zhàn)選項(xiàng)卡(詳解)
- 關(guān)于javascript事件響應(yīng)的基礎(chǔ)語法總結(jié)(必看篇)
- 深入理解JavaScript中的語法和代碼結(jié)構(gòu)
相關(guān)文章
統(tǒng)一接口:為FireFox添加IE的方法和屬性的js代碼
統(tǒng)一接口:為FireFox添加IE的方法和屬性的js代碼...2007-03-03
如何通過Proxy實(shí)現(xiàn)JSBridge模塊化封裝
這篇文章主要介紹了如何通過Proxy實(shí)現(xiàn)JSBridge模塊化封裝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
《javascript設(shè)計(jì)模式》學(xué)習(xí)筆記三:Javascript面向?qū)ο蟪绦蛟O(shè)計(jì)單例模式原理與實(shí)現(xiàn)方法分析
這篇文章主要介紹了Javascript面向?qū)ο蟪绦蛟O(shè)計(jì)單例模式原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了《javascript設(shè)計(jì)模式》中Javascript面向?qū)ο髥卫J较嚓P(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
js性能優(yōu)化 如何更快速加載你的JavaScript頁面
JavaScript現(xiàn)在極其重要。一些網(wǎng)站使用JavaScript來增添魅力;如今的許多Web應(yīng)用程序依賴它;其中一些甚至是完全用JavaScript編寫而成的。我在本文中將指出一些重要的規(guī)則,介紹如何使用你的JavaScript、使用哪些工具以及你將從中得到什么好處2012-03-03
JavaScript模擬可展開、拖動(dòng)與關(guān)閉的聊天窗口實(shí)例
這篇文章主要介紹了JavaScript模擬可展開、拖動(dòng)與關(guān)閉的聊天窗口,實(shí)例分析了javascript實(shí)現(xiàn)可拖動(dòng)的div層相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05

