摘要:事實上,最新的已經(jīng)支持了私有屬性。而的私有方法是提案的一部分。自從年雙十一正式上線,累計處理了億錯誤事件,付費客戶有金山軟件百姓網(wǎng)等眾多品牌企業(yè)。
譯者按: 為什么偏要用#符號?
原文:JavaScript"s new #private class fields
譯者:Fundebug
本文采用意譯,版權(quán)歸原作者所有
proposal-class-fields與proposal-private-methods定義了 Class 的私有屬性以及私有方法,這 2 個提案已經(jīng)處于 Stage 3,這就意味著它們已經(jīng)基本確定下來了,等待被加入到新的 ECMAScript 版本中。事實上,最新的 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 個部分:
定義 Class 私有屬性
引用 Class 私有屬性
定義 Class 私有屬性私有屬性與公共屬性的定義方式幾乎是一樣的,只是需要在屬性名稱前面添加#符號:
class Foo { publicFieldName = 1; #privateFieldName = 2; }
定義私有屬性的時候也可以不用賦值:
class Foo { #privateFieldName; }引用 Class 私有屬性
引用私有屬性也只需要使用#就好了。
class Foo { publicFieldName = 1; #privateFieldName = 2; add() { return this.publicFieldName + this.#privateFieldName; } }
其中,this.#可以簡化,去掉 this 也沒問題,下面兩種寫法是等價的:
method() { #privateFieldName; }
method() { this.#privateFieldName; }在 Class 定義中引用 Class 實例的私有屬性
對于私有屬性,我們是不可以直接通過 Class 實例來引用的,這也是私有屬性的本來含義。但是有一種情況除外,在 Class 定義中,我們可以引用 Class 實例的私有屬性:
class Foo { #privateValue = 42; static getPrivateValue(foo) { return foo.#privateValue; } } Foo.getPrivateValue(new Foo()); // >> 42
其中,foo是Foo的實例,在 Class 定義中,我們可以通過 foo 來引用私有屬性#privateValue。
Class 的私有方法Class 的私有屬性是提案proposal-class-fields的一部分,這個提案只關(guān)注 Class 的屬性,它并沒有對 Class 的方法進行任何修改。而 Class 的私有方法是提案proposal-class-fields的一部分。
Class 的私有方法語法如下:
class Foo { constructor() { this.#method(); } #method() { // ... } }
我們也可以將函數(shù)賦值給私有屬性:
class Foo { constructor() { this.#method(); } #method = () => { // ... }; }封裝(隱藏)私有屬性
我們不能直接通過 Class 實例引用私有屬性,我們只能在 Class 定義中引用它們:
class Foo { #bar; method() { this.#bar; // Works } } let foo = new Foo(); foo.#bar; // Invalid!
另外,要做到真正的私有的話,我們應(yīng)該無法檢測這個私有屬性是否存在,因此,我們需要允許定義同名的公共屬性:
class Foo { bar = 1; // public bar #bar = 2; // private bar }
如果我們不允許公共屬性與私有屬性同名,我們則可以通過給同名的公共屬性復(fù)制監(jiān)測該私有屬性是否存在:
foo.bar = 1; // Error: `bar` is private! (報錯,說明私有屬性存在)
不報錯也行:
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?。
為什么使用#符號?很多人都有一個疑問,為什么 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ū)分私有屬性和公共屬性。在定義和引用私有屬性的時候,使用#符號,私有屬性與公共屬性可以很好地區(qū)分開來。
為什么引用私有屬性的時候需要#符號?引用私有屬性的時候,我們需要this.#field,而不是this.field,原因如下:
因為我們需要封裝私有屬性,我們需要允許公共屬性與私有屬性同名,因此私有屬性與公共屬性的引用方式必須不一樣。這一點我們在前文已經(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)致我們每次都需要去檢查屬性是公共的還是私有的,這會造成嚴重的性能問題。
這篇文章遵循Creative Commons Attribution 4.0 International License。
參考Why is encapsulation a goal of this proposal?
關(guān)于FundebugFundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應(yīng)用實時BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網(wǎng)等眾多品牌企業(yè)。歡迎大家免費試用!
版權(quán)聲明
轉(zhuǎn)載時請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/201...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103786.html
摘要:類才支持實例屬性代碼解讀上面暫時只是概念性的寫法,事實上,的類只是一個原型鏈的語法糖而已,主要是從寫法上更接近于面相對象的類而已,另外一個作用就是區(qū)分的構(gòu)造函數(shù)和函數(shù)之間的區(qū)分。 ES5的原型鏈和ES6的類實現(xiàn)詳解 JavaScript最初設(shè)計時受到了面相對象編程的影響,從而引入了new關(guān)鍵字,來實例化對象。而在ES5中new后面跟著的是構(gòu)造函數(shù)(也是函數(shù)),而到了ES6則改成了cla...
摘要:類才支持實例屬性代碼解讀上面暫時只是概念性的寫法,事實上,的類只是一個原型鏈的語法糖而已,主要是從寫法上更接近于面相對象的類而已,另外一個作用就是區(qū)分的構(gòu)造函數(shù)和函數(shù)之間的區(qū)分。 ES5的原型鏈和ES6的類實現(xiàn)詳解 JavaScript最初設(shè)計時受到了面相對象編程的影響,從而引入了new關(guān)鍵字,來實例化對象。而在ES5中new后面跟著的是構(gòu)造函數(shù)(也是函數(shù)),而到了ES6則改成了cla...
摘要:它繼承自構(gòu)造函數(shù)被執(zhí)行,相應(yīng)的參數(shù)會被傳入,同時上下文會指向這個新的實例除非明確返回值,否則返回新的實例至此,我們實現(xiàn)了里面的類對象和屬性的概念,和有相同的屬性,但是值并不相同即屬性是私有的。 眾所周知,JS并沒有類(class)的概念,雖然說ES6開始有了類的概念,但是,這并不是說JS有了像Ruby、Java這些基于類的面向?qū)ο笳Z言一樣,有了全新的繼承模型。ES6中的類,僅僅只是基于...
摘要:可能不會包括所有的語法提案。事實上,有些提案已經(jīng)被擱置很多年了。因此,很可能也會在今年月份發(fā)布。 譯者按: 又過了1年... 原文:Whats New in JavaScript for 2019 譯者: Fundebug 為了保證可讀性,本文采用意譯而非直譯。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。 最近這些年,ECMASCript標(biāo)準發(fā)展節(jié)奏非常穩(wěn)定,每年都會發(fā)布新的特...
摘要:序內(nèi)部類是定義在另一個類內(nèi)部的類。之所以定義在內(nèi)部是因為內(nèi)部類有一些普通類沒有的特權(quán),可以方便實現(xiàn)一些需求。還有明確的使用內(nèi)部類的構(gòu)建函數(shù)。在以后,使用表達式會比匿名內(nèi)部類更加方便。 我的博客 轉(zhuǎn)載請注明原創(chuàng)出處。 序 內(nèi)部類(inner class)是定義在另一個類內(nèi)部的類。之所以定義在內(nèi)部是因為內(nèi)部類有一些普通類沒有的特權(quán),可以方便實現(xiàn)一些需求。 內(nèi)部類 先來看一個簡單的例子...
閱讀 1942·2021-10-11 10:59
閱讀 1047·2021-09-07 09:59
閱讀 2244·2021-08-27 16:17
閱讀 2798·2019-08-30 15:54
閱讀 2286·2019-08-30 12:58
閱讀 1787·2019-08-30 12:53
閱讀 1480·2019-08-28 18:13
閱讀 742·2019-08-26 13:35