JavaScript進階(十二):defineProperty 的基本使用

這篇博客我們來講下可響應對象的第二種方法,defineProperty。

儘管來說這個東西有衆多的缺陷,但畢竟是非常有一席之地的一個東西,所以我們現在還是要比較深入的瞭解它一下。

 

首先這個 defineProperty 它的作用是什麼?

就如它的名字所說的一樣,它可以幫助我們來定義一個屬性,只不過它定義出來的屬性,不是普通的屬性,是一個可以被監控,可以被監聽的一個狀態。

 

我們先來了解一下它的基本的語法,從最簡單的開始說起。

首先,我們定義一個 json:

那麼這個 json 是幹什麼的呢?其實它纔是我們真正的那個數據。

 

然後在接下來,我們需要調用 Object.definProperty,在它裏面,需要三個參數:

第一個參數,你需要告訴它,你要給哪個對象增加一個屬性。

第二個參數,那個屬性的名字。

比如我們給它加一個 a:

第三個參數則是一個對象,它裏面可以放一些選項,你所有的操作,都是在這裏面來規定的。

比如,你想怎麼控制,能不能改,能不能刪?還是怎麼樣,都是在這裏面來做的。

而它裏面,有 2 個最有用的東西,一個叫 get,一個叫 set:

這裏順便一說,defineProperty 的這個 get 和 set,它只是名字叫 get 和 set,跟我們上篇博客講的訪問器是兩碼事。

訪問器的 get 和 set 後面是有名字的

get xxx() { ... }

set xxx() { ... }

而 defineProperty 是這樣寫的:

get() { ... }

set() { ... }

defineProperty 的這個不是訪問器,它就只是一個叫 get 或者 set 的方法。

這裏大家要分清楚,不要搞混了。

 

然後 defineProperty 裏面的 get 和 set,這兩個東西的作用,和訪問器幾乎是一模一樣的。什麼作用呢?

就是我可以在讀取或者設置的時候,攔截這些操作。

 

那麼現在我們就來做的看下,我們先看看 json 裏面有沒有 a:

可以看到,是有的。

注意,這個 a 哪來的,我們並沒有給 json 加啊?

其實是 defineProperty 它加上的,因爲它就是用來添加屬性的,並且它調用的就是那個 get。

set 也是一樣的,從這個角度上來說,defineProperty 可以跟訪問器的 get、set 一樣來玩。

 

然後,我們現在希望有一個真實的數據,它是能變的,如果我們在 json 裏面又加了一個 a 會怎麼樣呢?

我們來試試:

並且我們在 get 裏面 return 的是 json.a,同時 set 裏面也是 json.a = val:

這個時候,當我們去訪問 a 或者去賦值 a 的時候:

可以看到,和之前的訪問器一樣,也出現無限死循環了。

所以名字得岔開,這個並不是某個特例。

所以我們需要加個下劃線 _a:

這個時候,我們訪問或者賦值的時候,就執行了 get 或者 set 了。

 

當然,還有個小事,這裏順便說一下。

我們的這個 json,表面上看起來,它是隻有一個 _a 的:

但是如果你把它展開,你會發現,它裏面還有個 get a 和 set a。

所以我們的這個 defineProperty,其實它的一個結果,是可以直接在 F12 裏面能夠看到的。

不知道大家有沒有注意過,我們在使用某個框架的時候,當你把它那個對象展開,就會發現它裏面有很多虛的,淺紫色的東西。

這些東西其實就證明,這是一個虛的,一個抽象的東西,它並不是真正存在的。

比如我直接去找 json 裏面有沒有一個 a,你根本就找不了:

其實你是被迫的需要執行 get a 這個函數,它只是一個虛的東西,並不是一個真實的方法,這就是它的由來。

 

所以到這爲止,我們就大概的理解了 defineProperty 的作用。

其實也沒什麼,它就是給某個對象,比方說 json,我們給它添加了一個 'a',表面上看來是一個屬性,但其實它背後對應的是一些函數,然後在裏面我們可以進行各種各樣的操作。

 

然後接下來,我們還有一個小事,就是我們平常對數據進行操作,不一定只是獲取和設置,有沒有可能我想把這個數據刪了?

比如,現在我就要把這個 json.a 刪除掉:

這時候它給我返回一個 false。

相信大家都能猜到這個 false 的意思,代表着沒刪掉。

比如,我們再次訪問 json.a:

可以看到,這個 json 它依然是有 a 的。

注意,用 defineProperty 去設置的屬性,不是直接用 delete 就能刪掉的,我們還需要一個東西才行。

實際上來說,這時候我們就需要用到它裏面的其他參數了,它裏面還有其他的一些參數可以供我們來選擇,並不是只有 get 和 set。

 

所以這時候,我們就需要一個東西,叫做 configurable,就是可配置的意思。

當我們沒寫的時候,configurable 默認會是一個 false:

可以看到,當我們寫上 configurable: false 的時候,它還是刪不了,和沒加一樣。

因爲 configurable 默認就是 false,不可配置嘛。

那如果我們給它一個 true,意思就是說,我這個屬性 a 是可配置的,可配置就意味着可以刪:

可以看到,現在 delete 就是 true 了。

並且現在我在找 json.a,它就是 undefined 了。

因爲剛纔那個 get 和 set 就都消失了,它就是幹這個用的。

 

那麼我們稍微來總結一下:

你可以看到 defineProperty 就比我們上篇博客說的訪問器,更爲的複雜,當然功能也更加的強大。

當你去定義某一個屬性的時候,你可以指定很多的東西,當然我們現在說的是最實用的三個東西:get,set,configurable。(其實它還有別的東西,不過意義和用處不大,我們一般就用這三個)

然後定義屬性的時候,可以順便的去指定一些屬性的行爲,比如是否可配置。(可配置包括 2 個,改和刪,一般情況下,我們用的都是刪除)

 

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