日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JS屬性特性(屬性描述符)

概念

創(chuàng)新互聯(lián)擁有網(wǎng)站維護技術(shù)和項目管理團隊,建立的售前、實施和售后服務(wù)體系,為客戶提供定制化的成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)站維護、香港機房服務(wù)器托管解決方案。為客戶網(wǎng)站安全和日常運維提供整體管家式外包優(yōu)質(zhì)服務(wù)。我們的網(wǎng)站維護服務(wù)覆蓋集團企業(yè)、上市公司、外企網(wǎng)站、商城網(wǎng)站定制開發(fā)、政府網(wǎng)站等各類型客戶群體,為全球成百上千家企業(yè)提供全方位網(wǎng)站維護、服務(wù)器維護解決方案。

ECMAScript 5 中定義了一個名叫“屬性描述符”的對象,用于描述了的各種特征。屬性描述符對象有4個屬性:

  • configurable:可配置性,控制著其描述的屬性的修改,表示能否修改屬性的特性,能否把屬性修改為訪問器屬性,或者能否通過delete刪除屬性從而重新定義屬性。默認值為true。
  • enumerable:可枚舉性,表示能否通過for-in遍歷得到屬性。默認值為true。
  • writable:可寫性,表示能否修改屬性的值。默認值為true。
  • value:數(shù)據(jù)屬性,表示屬性的值。默認值為undefined。

除了上面的屬性,還有兩個存取器屬性,分別是get和set,可以代替value和writable。

  • get:在讀取屬性時調(diào)用的函數(shù)。只指定get則表示屬性為只讀屬性。默認值為undefined。
  • set:在寫入屬性時調(diào)用的函數(shù)。只指定set則表示屬性為只寫屬性。默認值為undefined。

使用

“屬性描述符”對象只能在Object.defineProperty或Object.defineProperties中使用。

API 用法

Object.defineProperty:https://developer.mozilla.org...

Object.defineProperties: https://developer.mozilla.org...

 
 
  1. var hello = {}
  2. Object.defineProperty(hello, 'girl', {
  3.     configurable: false,
  4.     enumberable: false,
  5.     writable: true,
  6.     value: 'sexy'
  7. })
  8. // 存取器
  9. Object.defineProperty(hello, 'woman', {
  10.     configurable: false,
  11.     enumberable: false,
  12.     get: function() {
  13.         return this.girl
  14.     },
  15.     set: function(val) {
  16.         this.girl = val
  17.     }
  18. })
  19. // 定義多個屬性
  20. Object.defineProperties(hello, {
  21.     boy: {
  22.         configurable: false,
  23.         enumberable: false,
  24.         writable: false,
  25.         value: 'handsome'
  26.     },
  27.     man: {
  28.         configurable: false,
  29.         enumberable: false,
  30.         writable: true,
  31.         get: function() {
  32.             return this.boy
  33.         }
  34.     }
  35. }) 

當用Object.defineProperty或Object.defineProperties操作(新建或者修改)那些不允許創(chuàng)建或修改的屬性時,會拋出類型錯誤異常。

 
 
  1. // 此例子運行在前面的例子的基礎(chǔ)上
  2. Object.defineProperty(hello, 'boy', {
  3.     writable: true
  4. })    // Uncaught TypeError: Cannot redefine property: boy 

因為前面boy屬性已經(jīng)被設(shè)置為不可配置,所以這里修改writable會拋出類型錯誤異常。

通過Object.getOwnPropertyDescriptor或者Object.getOwnPropertyDescriptors可以得到屬性描述符。

API 用法

Object.getOwnPropertyDscriptor:https://developer.mozilla.org...

Object.getOwnPropertyDescriptors:https://developer.mozilla.org...

規(guī)則

 
 
  1. var rules = {
  2.     common: 'test'

如果屬性是不可配置的,則不能修改它的可配置性和可枚舉性。

 
 
  1. Object.defineProperty(rules, 'rule1', {
  2.     configurable: false,
  3.     enumberable: false
  4. })
  5. // 修改configurable會拋出類型錯誤異常
  6. Object.defineProperty(rules, 'rule1', {
  7.     configurable: true
  8. })    // Uncaught TypeError: Cannot redefine property: rule1
  9. // 修改enumberable不會拋出異常,但enmuberable沒有被修改
  10. Object.defineProperty(rules, 'rule1', {
  11.     enumberable: true
  12. })
  13. Object.getOwnPropertyDescriptor(rules, 'rule1')    // Object {value: undefined, writable: false, enumerable: false, configurable: false} 

如果存取器屬性是不可配置的,則不能修改get和set方法,也不能將它轉(zhuǎn)換為數(shù)據(jù)屬性。

 
 
  1. Object.defineProperty(rules, 'rule2', {
  2.     configurable: false,
  3.     enumberable: false,
  4.     get: function() {
  5.         return this.common
  6.     },
  7.     set: function(val) {
  8.         this.common = val
  9.     }
  10. })
  11. // 修改get或者set方法會拋出類型錯誤異常
  12. Object.defineProperty(rules, 'rule2', {
  13.     get: function() {
  14.         return this.common + 'rule2'
  15.     }
  16. })    // Uncaught TypeError: Cannot redefine property: rule2
  17. Object.defineProperty(rules, 'rule2', {
  18.     set: function(val) {
  19.         this.common = 'rule2'
  20.     }
  21. })    // Uncaught TypeError: Cannot redefine property: rule2
  22. // 將它轉(zhuǎn)換為數(shù)據(jù)屬性同樣會拋出類型錯誤異常
  23. Object.defineProperty(rules, 'rule2', {
  24.     value: 'rule2'
  25. })    // Uncaught TypeError: Cannot redefine property: rule2 

如果數(shù)據(jù)屬性是不可配置的,則不能將它轉(zhuǎn)換為存取器屬性;同時,也不能將它的可寫性從false修改為true,但可以從true修改為false。

 
 
  1. Object.defineProperty(rules, 'rule3', {
  2.     configurable: false,
  3.     writable: false,
  4.     value: 'rule3'
  5. })
  6. // 修改writable為true會拋出類型錯誤異常
  7. Object.defineProperty(rules, 'rule3', {
  8.     writable: true
  9. })
  10. Object.defineProperty(rules, 'rule4', {
  11.     configurable: false,
  12.     writable: true,
  13.     value: 'rule4'
  14. })
  15. // 可以修改writable為false
  16. Object.defineProperty(rules, 'rule4', {
  17.     writable: false
  18. })
  19. Object.getOwnPropertyDescriptor(rules, 'rule4')    //   Object {value: "rule4", writable: false, enumerable: false, configurable: false} 

如果數(shù)據(jù)屬性是不可配置且不可寫的,則不能修改他的值;如果是可配置但不可寫,則可以修改他的值(實際上是先將它標記為可寫的,然后修改它的值,***再將它標記回不可寫)。

其實這里所說的修改值,是通過Object.defineProperty或Object.defineProperties方法修改。通過直接賦值的方法在數(shù)據(jù)屬性不可配置的情況下是不能修改屬性值的。

 
 
  1. Object.defineProperty(rules, 'rule5', {
  2.     configurable: false,
  3.     writable: false,
  4.     value: 'rule5'
  5. })
  6. // 修改屬性值會拋出類型錯誤異常
  7. Object.defineProperty(rules, 'rule5', {
  8.     value: 'rule55'
  9. })    // Uncaught TypeError: Cannot redefine property: rule5
  10. rules.rule5 = 'rule55'
  11. // 值沒有被修改,也不會拋出異常
  12. rules.rule5            // 'rule5'
  13. Object.defineProperty(rules, 'rule6', {
  14.     configurable: true,
  15.     writable: false,
  16.     value: 'rule6'
  17. })
  18. // 修改屬性值
  19. Object.defineProperty(rules, 'rule6', {
  20.     value: 'rule66'
  21. })
  22. rules.rule6            // 'rule66'
  23. rules.rule6 = 'rule6'
  24. // 值沒有被修改,也不會修改
  25. rules.rule6            // 'rule6' 

只指定set不能讀,如果嘗試讀取該屬性值,返回undefined。(紅寶書上說在嚴格模式下才拋出異常,但沒有)

 
 
  1. Object.defineProperty(rules, 'rule7', {
  2.     get: function() {
  3.         return this.common
  4.     }
  5. })
  6. rules.rule7 = 'rule7'    // Uncaught TypeError: Cannot redefine property: rule7 

如果對象是不可擴展的,則可以編輯已有的自有屬性,但不能給它添加新屬性。

操作對象可擴展性的API有三個:Object.preventExtensions、Object.seal、Object.freeze。

API 用法

Object.preventExtensions:https://developer.mozilla.org...

Object.seal:https://developer.mozilla.org...

Object.freeze:https://developer.mozilla.org...

Object.isExtensions:https://developer.mozilla.org...

Object.isSealed:https://developer.mozilla.org...

Object.isFrozen:https://developer.mozilla.org...

使用Object.preventExtensions可以將對象轉(zhuǎn)換為不可擴展。

使用Object.isExtensions來判斷對象是否可擴展。

 
 
  1. var ex = {}
  2. Object.defineProperty(ex, 'ex1', {
  3.     configurable: true,
  4.     writable: true,
  5.     value: 'ex1'
  6. })
  7. Object.isExtensible(ex)        // true
  8. Object.preventExtensions(ex)
  9. Object.isExtensible(ex)        // false
  10. // 可以修改已有的屬性
  11. Object.defineProperty(ex, 'ex1', {
  12.     writable: false,
  13.     value: 'ex11'
  14. })
  15. Object.getOwnPropertyDescriptor(ex, 'ex1')    // Object {value: "ex11", writable: false, enumerable: false, configurable: true}
  16. // 添加屬性會拋出類型錯誤異常
  17. Object.defineProperty(ex, 'ex2', {
  18.     value: 'ex2'
  19. })    // Uncaught TypeError: Cannot define property:ex2, object is not extensible. 

使用Object.seal除了可以將對象轉(zhuǎn)換為不可擴展的,還可以將對象的所有自有屬性都轉(zhuǎn)換為不可配置的。即不能給對象添加新屬性,而且它已有的屬性也不能刪除或者配置(這里同樣會遵循前面的規(guī)則)。

使用Object.isSealed來判斷對象是否封閉(sealed)。

 
 
  1. var se = {}
  2. Object.defineProperty(se, 'se1', {
  3.     configurable: true,
  4.     writable: false,
  5.     value: 'se1'
  6. })
  7. Object.isSealed(se)        // false
  8. Object.seal(se)
  9. Object.isSealed(se)        // true
  10. // 修改已有的屬性會拋出類型錯誤異常
  11. Object.defineProperty(se, 'se1', {
  12.     writable: true,
  13.     value: 'se11'
  14. })    // Uncaught TypeError: Cannot redefine property: se1
  15. // 添加屬性會拋出類型錯誤異常
  16. Object.defineProperty(se, 'se2', {
  17.     value: 'se2'
  18. })    // Uncaught TypeError: Cannot define property:se2, object is not extensible. 

使用Object.freeze除了將對象轉(zhuǎn)換為不可擴展的和將其屬性轉(zhuǎn)換為不可配置的之外,還可以將自有屬性轉(zhuǎn)換為只讀。(如果對象設(shè)置了set,存取器屬性將不會受影響,仍可以調(diào)用set方法,而且不會拋出異常,但如果set方法是改變該對象的屬性,則不能修改成功)

使用Object.isFrozen來檢測對象是否凍結(jié)(frozen)。

 
 
  1. var fr = {}
  2. Object.defineProperty(fr, 'fr1', {
  3.     configurable: true,
  4.     writable: false,
  5.     value: 'fr1'
  6. })
  7. Object.isFrozen(fr)        // false
  8. Object.freeze(fr)
  9. Object.isFrozen(fr)        // true
  10. // 修改已有的屬性會拋出類型錯誤異常
  11. Object.defineProperty(fr, 'fr1', {
  12.     writable: true,
  13.     value: 'fr11'
  14. })    // Uncaught TypeError: Cannot redefine property: fr1
  15. // 添加屬性會拋出類型錯誤異常
  16. Object.defineProperty(fr, 'fr2', {
  17.     value: 'fr2'
  18. })    // Uncaught TypeError: Cannot define property:fr2, object is not extensible.
  19. fr.fr1 = 'fr11'
  20. // 不能修fr1屬性
  21. fr.fr1            // 'fr1'
  22. var set = {}
  23. Object.defineProperty(set, 'set1', {
  24.     configurable: true,
  25.     value: 'set1'
  26. })
  27. Object.defineProperty(set, 'set2', {
  28.     configurable: true,
  29.     set: function(val) {
  30.         this.set1 = val
  31.     }
  32. })
  33. Object.isFrozen(set)        // false
  34. Object.freeze(set)
  35. Object.isFrozen(set)        // true
  36. set.set2 = 'set2'
  37. set.set1                    // 'set1' 

結(jié)語

我對屬性描述符很不熟悉,主要是因為平時用得少。不過最近,開始學寫一些小的庫(雖然很挫),就感覺屬性描述符有使用的場景了。我暫時能想到的就是將庫對象的一些屬性設(shè)置為只讀,以防止對象的一些屬性被用戶重寫覆蓋了。還有一個用法是在知乎和學vue的時候知道的,就是通過getter和setter實現(xiàn)“監(jiān)聽”對象屬性的數(shù)據(jù)更新(在這里挖一個坑。后面學習一下這種方法,再寫一篇“監(jiān)聽”對象屬性的數(shù)據(jù)更新的文章)。

***,如果大家知道更多屬性描述符的使用后場景,希望大家能在評論區(qū)留下你們的高見。


當前名稱:JS屬性特性(屬性描述符)
URL地址:http://www.dlmjj.cn/article/dpsijei.html