摘要:概念中定義了一個(gè)名叫屬性描述符的對(duì)象,用于描述了的各種特征。只指定則表示屬性為只讀屬性。使用屬性描述符對(duì)象只能在或中使用。修改已有的屬性會(huì)拋出類型錯(cuò)誤異常添加屬性會(huì)拋出類型錯(cuò)誤異常不能修屬性結(jié)語(yǔ)我對(duì)屬性描述符很不熟悉,主要是因?yàn)槠綍r(shí)用得少。
概念
ECMAScript 5 中定義了一個(gè)名叫“屬性描述符”的對(duì)象,用于描述了的各種特征。屬性描述符對(duì)象有4個(gè)屬性:
configurable:可配置性,控制著其描述的屬性的修改,表示能否修改屬性的特性,能否把屬性修改為訪問器屬性,或者能否通過delete刪除屬性從而重新定義屬性。默認(rèn)值為true。
enumerable:可枚舉性,表示能否通過for-in遍歷得到屬性。默認(rèn)值為true。
writable:可寫性,表示能否修改屬性的值。默認(rèn)值為true。
value:數(shù)據(jù)屬性,表示屬性的值。默認(rèn)值為undefined。
除了上面的屬性,還有兩個(gè)存取器屬性,分別是get和set,可以代替value和writable。
get:在讀取屬性時(shí)調(diào)用的函數(shù)。只指定get則表示屬性為只讀屬性。默認(rèn)值為undefined。
set:在寫入屬性時(shí)調(diào)用的函數(shù)。只指定set則表示屬性為只寫屬性。默認(rèn)值為undefined。
使用“屬性描述符”對(duì)象只能在Object.defineProperty或Object.defineProperties中使用。
API 用法
Object.defineProperty:https://developer.mozilla.org...
Object.defineProperties: https://developer.mozilla.org...
var hello = {} Object.defineProperty(hello, "girl", { configurable: false, enumberable: false, writable: true, value: "sexy" }) // 存取器 Object.defineProperty(hello, "woman", { configurable: false, enumberable: false, get: function() { return this.girl }, set: function(val) { this.girl = val } }) // 定義多個(gè)屬性 Object.defineProperties(hello, { boy: { configurable: false, enumberable: false, writable: false, value: "handsome" }, man: { configurable: false, enumberable: false, writable: true, get: function() { return this.boy } } })
當(dāng)用Object.defineProperty或Object.defineProperties操作(新建或者修改)那些不允許創(chuàng)建或修改的屬性時(shí),會(huì)拋出類型錯(cuò)誤異常。
// 此例子運(yùn)行在前面的例子的基礎(chǔ)上 Object.defineProperty(hello, "boy", { writable: true }) // Uncaught TypeError: Cannot redefine property: boy
因?yàn)榍懊?b>boy屬性已經(jīng)被設(shè)置為不可配置,所以這里修改writable會(huì)拋出類型錯(cuò)誤異常。
通過Object.getOwnPropertyDescriptor或者Object.getOwnPropertyDescriptors可以得到屬性描述符。
規(guī)則API 用法
Object.getOwnPropertyDescriptor:https://developer.mozilla.org...
Object.getOwnPropertyDescriptors:https://developer.mozilla.org...
var rules = { common: "test" }
如果屬性是不可配置的,則不能修改它的可配置性和可枚舉性。
Object.defineProperty(rules, "rule1", { configurable: false, enumberable: false }) // 修改configurable會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(rules, "rule1", { configurable: true }) // Uncaught TypeError: Cannot redefine property: rule1 // 修改enumberable不會(huì)拋出異常,但enmuberable沒有被修改 Object.defineProperty(rules, "rule1", { enumberable: true }) Object.getOwnPropertyDescriptor(rules, "rule1") // Object {value: undefined, writable: false, enumerable: false, configurable: false}
如果存取器屬性是不可配置的,則不能修改get和set方法,也不能將它轉(zhuǎn)換為數(shù)據(jù)屬性。
Object.defineProperty(rules, "rule2", { configurable: false, enumberable: false, get: function() { return this.common }, set: function(val) { this.common = val } }) // 修改get或者set方法會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(rules, "rule2", { get: function() { return this.common + "rule2" } }) // Uncaught TypeError: Cannot redefine property: rule2 Object.defineProperty(rules, "rule2", { set: function(val) { this.common = "rule2" } }) // Uncaught TypeError: Cannot redefine property: rule2 // 將它轉(zhuǎn)換為數(shù)據(jù)屬性同樣會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(rules, "rule2", { value: "rule2" }) // Uncaught TypeError: Cannot redefine property: rule2
如果數(shù)據(jù)屬性是不可配置的,則不能將它轉(zhuǎn)換為存取器屬性;同時(shí),也不能將它的可寫性從false修改為true,但可以從true修改為false。
Object.defineProperty(rules, "rule3", { configurable: false, writable: false, value: "rule3" }) // 修改writable為true會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(rules, "rule3", { writable: true }) Object.defineProperty(rules, "rule4", { configurable: false, writable: true, value: "rule4" }) // 可以修改writable為false Object.defineProperty(rules, "rule4", { writable: false }) Object.getOwnPropertyDescriptor(rules, "rule4") // Object {value: "rule4", writable: false, enumerable: false, configurable: false}
如果數(shù)據(jù)屬性是不可配置且不可寫的,則不能修改他的值;如果是可配置但不可寫,則可以修改他的值(實(shí)際上是先將它標(biāo)記為可寫的,然后修改它的值,最后再將它標(biāo)記回不可寫)。
其實(shí)這里所說(shuō)的修改值,是通過Object.defineProperty或Object.defineProperties方法修改。通過直接賦值的方法在數(shù)據(jù)屬性不可配置的情況下是不能修改屬性值的。
Object.defineProperty(rules, "rule5", { configurable: false, writable: false, value: "rule5" }) // 修改屬性值會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(rules, "rule5", { value: "rule55" }) // Uncaught TypeError: Cannot redefine property: rule5 rules.rule5 = "rule55" // 值沒有被修改,也不會(huì)拋出異常 rules.rule5 // "rule5" Object.defineProperty(rules, "rule6", { configurable: true, writable: false, value: "rule6" }) // 修改屬性值 Object.defineProperty(rules, "rule6", { value: "rule66" }) rules.rule6 // "rule66" rules.rule6 = "rule6" // 值沒有被修改,也不會(huì)修改 rules.rule6 // "rule6"
只指定get不能寫,如果嘗試對(duì)該屬性賦值,會(huì)拋出類型錯(cuò)誤異常。(紅寶書上說(shuō)只有在嚴(yán)格模式下才拋出異常)
Object.defineProperty(rules, "rule7", { get: function() { return this.common } }) rules.rule7 = "rule7" // Uncaught TypeError: Cannot redefine property: rule7
只指定set不能讀,如果嘗試讀取該屬性值,返回undefined。(紅寶書上說(shuō)在嚴(yán)格模式下才拋出異常,但沒有)
Object.defineProperty(rules, "rule8", { set: function() { this.common = "rule8" } }) rules.rule8 // undefined
如果對(duì)象是不可擴(kuò)展的,則可以編輯已有的自有屬性,但不能給它添加新屬性。
操作對(duì)象可擴(kuò)展性的API有三個(gè):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可以將對(duì)象轉(zhuǎn)換為不可擴(kuò)展。
使用Object.isExtensions來(lái)判斷對(duì)象是否可擴(kuò)展。
var ex = {} Object.defineProperty(ex, "ex1", { configurable: true, writable: true, value: "ex1" }) Object.isExtensible(ex) // true Object.preventExtensions(ex) Object.isExtensible(ex) // false // 可以修改已有的屬性 Object.defineProperty(ex, "ex1", { writable: false, value: "ex11" }) Object.getOwnPropertyDescriptor(ex, "ex1") // Object {value: "ex11", writable: false, enumerable: false, configurable: true} // 添加屬性會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(ex, "ex2", { value: "ex2" }) // Uncaught TypeError: Cannot define property:ex2, object is not extensible.
使用Object.seal除了可以將對(duì)象轉(zhuǎn)換為不可擴(kuò)展的,還可以將對(duì)象的所有自有屬性都轉(zhuǎn)換為不可配置的。即不能給對(duì)象添加新屬性,而且它已有的屬性也不能刪除或者配置(這里同樣會(huì)遵循前面的規(guī)則)。
使用Object.isSealed來(lái)判斷對(duì)象是否封閉(sealed)。
var se = {} Object.defineProperty(se, "se1", { configurable: true, writable: false, value: "se1" }) Object.isSealed(se) // false Object.seal(se) Object.isSealed(se) // true // 修改已有的屬性會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(se, "se1", { writable: true, value: "se11" }) // Uncaught TypeError: Cannot redefine property: se1 // 添加屬性會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(se, "se2", { value: "se2" }) // Uncaught TypeError: Cannot define property:se2, object is not extensible.
使用Object.freeze除了將對(duì)象轉(zhuǎn)換為不可擴(kuò)展的和將其屬性轉(zhuǎn)換為不可配置的之外,還可以將自有屬性轉(zhuǎn)換為只讀。(如果對(duì)象設(shè)置了set,存取器屬性將不會(huì)受影響,仍可以調(diào)用set方法,而且不會(huì)拋出異常,但如果set方法是改變?cè)搶?duì)象的屬性,則不能修改成功)
使用Object.isFrozen來(lái)檢測(cè)對(duì)象是否凍結(jié)(frozen)。
var fr = {} Object.defineProperty(fr, "fr1", { configurable: true, writable: false, value: "fr1" }) Object.isFrozen(fr) // false Object.freeze(fr) Object.isFrozen(fr) // true // 修改已有的屬性會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(fr, "fr1", { writable: true, value: "fr11" }) // Uncaught TypeError: Cannot redefine property: fr1 // 添加屬性會(huì)拋出類型錯(cuò)誤異常 Object.defineProperty(fr, "fr2", { value: "fr2" }) // Uncaught TypeError: Cannot define property:fr2, object is not extensible. fr.fr1 = "fr11" // 不能修fr1屬性 fr.fr1 // "fr1"
var set = {} Object.defineProperty(set, "set1", { configurable: true, value: "set1" }) Object.defineProperty(set, "set2", { configurable: true, set: function(val) { this.set1 = val } }) Object.isFrozen(set) // false Object.freeze(set) Object.isFrozen(set) // true set.set2 = "set2" set.set1 // "set1"結(jié)語(yǔ)
我對(duì)屬性描述符很不熟悉,主要是因?yàn)槠綍r(shí)用得少。不過最近,開始學(xué)寫一些小的庫(kù)(雖然很挫),就感覺屬性描述符有使用的場(chǎng)景了。我暫時(shí)能想到的就是將庫(kù)對(duì)象的一些屬性設(shè)置為只讀,以防止對(duì)象的一些屬性被用戶重寫覆蓋了。還有一個(gè)用法是在知乎和學(xué)vue的時(shí)候知道的,就是通過getter和setter實(shí)現(xiàn)“監(jiān)聽”對(duì)象屬性的數(shù)據(jù)更新(在這里挖一個(gè)坑。后面學(xué)習(xí)一下這種方法,再寫一篇“監(jiān)聽”對(duì)象屬性的數(shù)據(jù)更新的文章)。
最后,如果大家知道更多屬性描述符的使用后場(chǎng)景,希望大家能在評(píng)論區(qū)留下你們的高見。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/91094.html
摘要:需被定義或修改的屬性名。當(dāng)且僅當(dāng)該屬性出現(xiàn)在相應(yīng)的對(duì)象枚舉屬性中。可以是任何有效的值數(shù)值,對(duì)象,函數(shù)等。方法將返回用作屬性的值。該方法將收到作為唯一參數(shù)的新值分配給屬性。屬性用來(lái)聲明欲修飾屬性是否可以被枚舉。 定義 getter 與 setter 通過對(duì)象初始化器定義 使用 Object.create 方法 使用 Object.defineProperty 方法 使用 Objec...
摘要:屬性描述符升級(jí)打怪必備技能對(duì)象有自己的屬性和方法,對(duì)于我們對(duì)象的屬性來(lái)講,屬性還有自己的屬性,又稱為屬性描述符。這個(gè)方法接受三個(gè)參數(shù),第一個(gè)是指定的對(duì)象,第二個(gè)是指定的對(duì)象參數(shù),第三個(gè)當(dāng)然是要修改的屬性描述符了。 對(duì)象的聲明有倆種: 字面量 通過new一個(gè)構(gòu)造函數(shù)Object 兩者唯一的區(qū)別就是,字面量形式,可以一次賦值多個(gè),通過new Object就得一個(gè)一個(gè)賦值 數(shù)據(jù)類型 ...
摘要:數(shù)據(jù)屬性有個(gè)描述其行為的特性表示能否通過刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。總結(jié)一波關(guān)于這些內(nèi)容主要講的就是在的對(duì)象屬性可以分為兩類,一類就是數(shù)據(jù)屬性,一類就是訪問器屬性。 前言 面向?qū)ο蟮恼Z(yǔ)言都有一個(gè)類的概念,通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象。 JavaScript中把對(duì)象定義為無(wú)序?qū)傩缘募希瑢傩钥梢园局担瑢?duì)象或者函數(shù)...
摘要:語(yǔ)法將要被添加屬性或修改屬性的對(duì)象該對(duì)象的一個(gè)或多個(gè)鍵值對(duì)定義了將要為對(duì)象添加或修改的屬性的具體配置張三張三功能該方法返回指定對(duì)象上一個(gè)自有屬性對(duì)應(yīng)的屬性描述符。 文章同步到github ECMAS-262第5版在定義只有內(nèi)部采用的特性時(shí),提供了描述了屬性特征的幾種屬性。ECMAScript對(duì)象中目前存在的屬性描述符主要有兩種,數(shù)據(jù)描述符(數(shù)據(jù)屬性)和存取描述符(訪問器屬性),數(shù)據(jù)描述...
摘要:之后,所有的屬性都存在屬性描述符這個(gè)屬性。獲取屬性描述符屬性的方法是以下面的代碼為例返回該方法返回的是一個(gè)對(duì)象,該對(duì)象除了包含為的屬性外,還包含了屬性的三個(gè)特性。 今天俺跟大家一起來(lái)學(xué)習(xí)一下一個(gè)很小的知識(shí)點(diǎn),那就是屬性描述符,需要注意的是該功能是在ES5之后才出現(xiàn)的,也就是說(shuō)ES5之前偉大的JS創(chuàng)造者并沒有開放出該功能~大家現(xiàn)在知道了吧,其實(shí)我們學(xué)習(xí)的語(yǔ)言并不是什么天生的大神創(chuàng)造的,本...
閱讀 1312·2021-11-11 10:57
閱讀 3728·2021-09-07 10:10
閱讀 3449·2021-08-03 14:03
閱讀 3075·2019-08-30 13:45
閱讀 689·2019-08-29 11:19
閱讀 1047·2019-08-28 18:07
閱讀 3105·2019-08-26 13:55
閱讀 816·2019-08-26 12:17