詳解JavaScript 新語法之Class 的私有屬性與私有方法
譯者按: 為什么偏要用 # 符號?
原文: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 私有屬性。
那么,對于 Class 的私有屬性與私有方法,它們究竟是什么呢?它們是怎樣工作的?為什么要使用#符號來定義呢?
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 私有屬性
私有屬性與公共屬性的定義方式幾乎是一樣的,只是需要在屬性名稱前面添加#符號:
class Foo { publicFieldName = 1; #privateFieldName = 2; }
定義私有屬性的時(shí)候也可以不用賦值:
class Foo { #privateFieldName; }
引用 Class 私有屬性
引用私有屬性也只需要使用#就好了。
class Foo { publicFieldName = 1; #privateFieldName = 2; add() { return this.publicFieldName + this.#privateFieldName; } }
其中,this.#可以簡化,去掉 this 也沒問題,下面兩種寫法是等價(jià)的:
method() { #privateFieldName; } method() { this.#privateFieldName; }
在 Class 定義中引用 Class 實(shí)例的私有屬性
對于私有屬性,我們是不可以直接通過 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 的屬性,它并沒有對 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)該無法檢測這個(gè)私有屬性是否存在,因此,我們需要允許定義同名的公共屬性:
class Foo { bar = 1; // public bar #bar = 2; // private bar }
如果我們不允許公共屬性與私有屬性同名,我們則可以通過給同名的公共屬性復(fù)制監(jiān)測該私有屬性是否存在:
foo.bar = 1; // Error: `bar` is private! (報(bào)錯(cuò),說明私有屬性存在)
不報(bào)錯(cuò)也行:
foo.bar = 1; foo.bar; // `undefined` (賦值失敗,說明私有屬性存在)
對于 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?。
為什么使用#符號?
很多人都有一個(gè)疑問,為什么 JS 不能學(xué)習(xí)其他語言,使用private來定義私有屬性和私有方法?為什么要使用奇怪的#符號?
使用 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; } }
對于這些語言屬性,私用屬性和公共屬性的引用方式是相同的,因此他們可以使用 private 來定義私有屬性。
但是,對于 JavaScript 來說,我們不能使用 this.field 來引用私有屬性(我接下來會解釋原因),我們需要在語法層面上區(qū)分私有屬性和公共屬性。在定義和引用私有屬性的時(shí)候,使用#符號,私有屬性與公共屬性可以很好地區(qū)分開來。
為什么引用私有屬性的時(shí)候需要#符號?
引用私有屬性的時(shí)候,我們需要this.#field,而不是this.field,原因如下:
•因?yàn)槲覀冃枰庋b私有屬性,我們需要允許公共屬性與私有屬性同名,因此私有屬性與公共屬性的引用方式必須不一樣。這一點(diǎn)我們在前文已經(jīng)詳述。
•公共屬性可以通過this.field以及this['field']來引用,但是私有屬性不能支持this['field']這種方式,否則會破壞私有屬性的隱私性,示例如下:
class Dict extends null { #data = something_secret; add(key, value) { this[key] = value; } get(key) { return this[key]; } } new Dict().get("#data"); // 返回私有屬性
因此,私有屬性與公共屬性的引用方式必須不一樣,否則會破壞this['field']語法。
•私有屬性與公共屬性的引用方式一樣的話,會導(dǎo)致我們每次都需要去檢查屬性是公共的還是私有的,這會造成嚴(yán)重的性能問題。
這篇文章遵循Creative Commons Attribution 4.0 International License。
參考
•Why is encapsulation a goal of this proposal?
總結(jié)
以上所述是小編給大家介紹的JavaScript 新語法之Class 的私有屬性與私有方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
- 溫習(xí)Javascript基礎(chǔ)語法之詞法結(jié)構(gòu)
- JavaScript語法約定和程序調(diào)試原理解析
- javascript中正則表達(dá)式語法詳解
- javascript 高級語法之繼承的基本使用方法示例
- JSON基本語法及與JavaScript的異同實(shí)例分析
- NodeJS模塊與ES6模塊系統(tǒng)語法及注意點(diǎn)詳解
- JavaScript ES6中的簡寫語法總結(jié)與使用技巧
- js es6系列教程 - 新的類語法實(shí)戰(zhàn)選項(xiàng)卡(詳解)
- 關(guān)于javascript事件響應(yīng)的基礎(chǔ)語法總結(jié)(必看篇)
- 深入理解JavaScript中的語法和代碼結(jié)構(gòu)
相關(guān)文章
JavaScript中ES6規(guī)范中l(wèi)et和const的用法和區(qū)別
這篇文章主要介紹了JavaScript中ES6規(guī)范中l(wèi)et和const的用法和區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08jsonp跨域獲取數(shù)據(jù)的基礎(chǔ)教程
這篇文章主要給大家介紹了關(guān)于jsonp跨域獲取數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Javascript實(shí)現(xiàn)Array和String互轉(zhuǎn)換的方法
這篇文章主要介紹了Javascript實(shí)現(xiàn)Array和String互轉(zhuǎn)換的方法,涉及JavaScript中toString方法與split方法的使用技巧,需要的朋友可以參考下2015-12-12javascript 動態(tài)數(shù)據(jù)下的錨點(diǎn)錯(cuò)位問題解決方法
用 Javascript 實(shí)現(xiàn)錨點(diǎn)(Anchor)間平滑跳轉(zhuǎn)2008-12-12微信小程序自定義組件的實(shí)現(xiàn)方法及自定義組件與頁面間的數(shù)據(jù)傳遞問題
這篇文章主要介紹了微信小程序自定義組件的實(shí)現(xiàn)方法及自定義組件與頁面間的數(shù)據(jù)傳遞 ,需要的朋友可以參考下2018-10-10一個(gè)可以得到元素真實(shí)的背景顏色的javascript腳本
一個(gè)可以得到元素真實(shí)的背景顏色的javascript腳本...2007-07-07JS實(shí)現(xiàn)隨機(jī)生成字符串(可指定長度)的示例代碼
本文主要介紹了JS實(shí)現(xiàn)隨機(jī)生成字符串(可指定長度)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)創(chuàng)建對象的方法分析
這篇文章主要介紹了JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)創(chuàng)建對象的方法,結(jié)合實(shí)例形式分析了javascript使用object構(gòu)造函數(shù)和對象字面量來創(chuàng)建對象的相關(guān)操作技巧,需要的朋友可以參考下2018-08-08動態(tài)統(tǒng)計(jì)當(dāng)前輸入內(nèi)容的字節(jié)、字符數(shù)的實(shí)例詳解
這篇文章主要介紹了動態(tài)統(tǒng)計(jì)當(dāng)前輸入內(nèi)容的字節(jié)、字符數(shù)的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10