溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript中Class私有屬性與私有方法的示例分析

發(fā)布時間:2021-08-19 11:45:39 來源:億速云 閱讀:1240 作者:小新 欄目:web開發(fā)

小編給大家分享一下JavaScript中Class私有屬性與私有方法的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

proposal-class-fieldsproposal-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 不能學習其他語言,使用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']語法。

?私有屬性與公共屬性的引用方式一樣的話,會導致我們每次都需要去檢查屬性是公共的還是私有的,這會造成嚴重的性能問題。

以上是“JavaScript中Class私有屬性與私有方法的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI