JavaScript進階(十一):可響應對象,accessor 訪問器

從這篇博客開始,我們就來說下,在前面就提到過的可響應對象,這個東西特別的重要。

 

那什麼叫做可響應對象呢?

用人話來說就是,它的屬性是可以被監聽的。

說白了就是,平常一個屬性放在那,就放在那了,不管你做了啥操作,這事直接就過去了。

而如果你用了可響應對象,你的屬性是可以被監聽起來的,你這邊做了任何的操作,我這邊都可以有一些反應。

 

那麼,爲什麼要這麼做?

就一個原因,爲了方便。

 

在這會給大家介紹三種方法:

1,accessor,訪問器。有的人也管它叫 get / set。

2,defineProperty。

實際上來說,看它名字,你就知道它是幹什麼的,define 定義,property 屬性,就是定義一個屬性。

所以它的作用,其實就在於,幫助你一個已有的對象,去添加一個特殊的屬性。

爲什麼呢?

比如我這裏有一個 json ,我給它加個 a:json.a = 12,這樣一點特殊的地方都沒有。

而如果我用了 defineProperty 之後,它的作用,就幫助我來添加一個可以被監聽的屬性,這個就不一樣的了。

當然這個東西它有一些的缺陷,所以我們最終用到的,是另外一個東西,叫做 Proxy。

3,proxy。

proxy,它應該來說是 defineProperty 的一個後續的版本。

說白了,它的功能非常的強大,它不但可以監聽的範圍比 defineProperty 廣的多,而且 defineProperty 的一些問題,它還沒有。

所以 proxy 很重要,也是非常好用的一個東西。

 

這篇博客講解的就是訪問器,那麼現在我們就正式開始。

首先我們就來看一個最簡單的例子,就是我怎麼樣才能讓一個東西,讓一個屬性,能夠響應我的操作。

比如,我有一個類,裏面有一個屬性 count,我們讓這個 count++

實際上來說,在這個時候,想都不用去想,沒有任何反應。

任何代碼都不會被執行,只是很單純的那個 count 會變:

但是,現在我就換一個寫法。

首先,有一個東西叫做 get,然後我在來一個 set:

這兩個東西就構成了一個對 count 的訪問器。

當然,在我這個對象的內部,我也得保存一個真正的數據。

我們前面也提到過,對於面向對象來說,有一個特別重要的概念,就是我希望能夠把它內部的這個成員,尤其是屬性,給它隱藏起來,不讓它被外面直接的操作。

所以這時候,我在這就放一個 _count:

注意,這個 count 是用下劃線來表示的。

下劃線在我們的成員當中,一般代表的是私有的,因爲我們的 js 到目前爲止,還不具備真正意義的私有成員。

像 ts,java 都有,一個 private 直接搞定,但 js 沒有真正的私有成員,所以我們就通過命名的方式,來對它做一定的標記。

 

所以以後你看到別人的類裏面有某個東西是下劃線開頭的,你千萬不要去用它,說明別人是刻意的把這個東西藏起來了,如果你去用了的話,那不定會出什麼事。

然後現在,說白了,這個 get 也好,set 也好,它們真正操作的其實是 this._count。

 

然後現在我們來看看 get,假設現在什麼都不寫的話,就沒有 return,也就是沒有值,那麼肯定是一個 undefined。

那麼現在我們來打印一個 a.count:

注意,儘管在這我用的是 a.count,是以一個屬性的方式在使用它,但是其實它背後會變成一個函數調用,來調 get count,這個就是訪問器它本身的一個作用。

先不管別的,我們先看看效果:

那麼在這個時候,你可以明確的看到,它就是一個 undefined。

爲什麼?因爲 a.count 對應的就是 get count,而我們的 get count 並沒有返回值,沒有 return,它就會默認的 return undefined。

比如,我們隨便返回一個值:

那麼你可以看到,是不是它打印出來的 a.count 就是在 get count 裏面 return 的那個值。

這個 count 可以跟 _count 有關聯,也可以沒關聯,這個完全是我自己說了算。

但是按照正常的情況,我們一般都是會返回它背後真實的數據:

然後現在這時候你可以看到,打印出來就是 12 了。

 

在接下來,當我們需要對這個 count 進行設置的時候,比如:

然後我們來看看 a.count:

你會發現賦值了也沒變。

原因很簡單,因爲賦值的時候,它背後會偷偷的調用 set count,而我們在 set count 裏面啥都沒做。

所以這時候,我們應該把這個東西存進去,這樣它才能夠有所變化:

說白了,我們現在所做的事,算是對這個 count 加了一道防火牆,什麼意思呢?

就是說,你進去也好,出來也好,不能直接進,也不能直接出,你需要先經過我的 get / set 函數。

當然,到目前爲止,我們都是簡單的給他設置,什麼都沒幹,那麼我們可以做一些其他的事情。

比如,這個 count 只能接收數字:

可以看到,當我們賦值 666666 的時候,是沒問題的。

如果我們賦值的是一個字符串,這時候就報錯了。

所以,我們可以看到,這個 count 它是被保護起來的。

並且,它還是 666666,亂七八糟的值是沒有進去的

現在這個時候我們就看到了這個 count 的作用,或者說訪問器它的一個作用。

可以說很簡單,它就一個 get,一個 set,多了沒有,就這兩個東西。

 

 

那麼可能有人會問 get,set 在這裏是什麼?

這個 get 和 set 是我們 js 裏面一個特殊的語法,它所定義的這個方法,不是通常意義上的方法。

通常意義上的方法, 是供我們調用的,而這 2 個加完之後,它會變成所謂的訪問器方法。

所謂訪問器方法,說白了就是說,你把我當做一個變量來用就可以。

然後你在讀取或者設置的時候,我會自動的去調用它背後的 get 或者 set 函數,你不用管,我來做。

所以,它就是幹這個事用的,爲了方便。

 

當然,順便一提,有人可能也會問,那我的這個屬性和方法重名行不行?

比如,我們把 _count 都改成 count:

我們先不說訪問器,就說平常,你一個屬性跟一個方法重名,這事本身靠譜嗎?本身就已經不靠譜了。

所以我們這麼寫,你可以看到,頁面上是會出現問題的。

 

爲什麼會報錯?

因爲我們在外面讀取 a.count 的時候,首先它會來到 get count,然後它會試圖 return this.count。

注意,當我們執行到 return this.count 的時候,這是不是又是一個讀取的操作?

去哪讀?又來到 get count 這讀,然後它會再 return this.count,這就無限死循環了。

所以這個時候,我們的真實數據,跟你的訪問器,名字要岔開,不然的話肯定是會出事的,這事不用想。

 

所以,訪問器這個東西,它的優點就是特別的簡單,隨手拿來就能用。

 

還記不記得我們之前博客裏面做過的熱門主播 HotList(js 進階三和四)。

我們當初是這麼來實現的:我們給 title,專門的配了一個 setTitle 和 getTitle,當時也是可以滿足我們的要求的。

比如,當我們 setTitle 之後,標題肯定是會變的:

但是說句特別實在的話,這事不方便,我希望的是這樣:

但我們知道這麼寫是不行的,因爲這個 title,它其實是一個普普通通的屬性,你對它進行賦值,不會有任何的操作。

所以,我們能不能把這個東西用訪問器來搞的更加的方便一點呢?當然是可以的。


首先,我們把 title 改成 _title:

爲什麼?

因爲我要把自己給隱藏起來,我不能隨便讓人去改。

 

接下來,我們要做的事,就來了:

首先,我們這邊就不希望在搞成 getTitle 和 setTitle 了,我們換成 get 和 set:

那麼有了這樣的一個東西之後,我們的事情就會變的非常的方便。

可以看到,現在的 list.title 是熱門主播,當我們進行 list.title = 'xxx' 賦值的時候:

可以看到,也是跟着變的,就像你在用一個變量一樣,非常的簡單,非常的方便。

說句實話,這個就和我們原先的 list.setTitle('xxx') 效果一樣,只不過現在這個更方便一些。

所以訪問器沒別的,就是爲了方便。

 

所以,就像我們最開始說的,這個訪問器特別的簡單,隨手就用,隨手就寫。

並且它的寫法也非常的簡單,就像普通的一個方法一樣來用,只不過前面有個關鍵字叫 get,set。

以及沒人規定說,必須 get 跟 set 配着來,你可以只有get,我這個屬性只讀的,我不提供修改操作,也是可以的。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章