摘要:語法將要被添加屬性或修改屬性的對象該對象的一個或多個鍵值對定義了將要為對象添加或修改的屬性的具體配置張三張三功能該方法返回指定對象上一個自有屬性對應的屬性描述符。
文章同步到github
ECMAS-262第5版在定義只有內部采用的特性時,提供了描述了屬性特征的幾種屬性。ECMAScript對象中目前存在的屬性描述符主要有兩種,數據描述符(數據屬性)和存取描述符(訪問器屬性),數據描述符是一個擁有可寫或不可寫值的屬性。存取描述符是由一對 getter-setter 函數功能來描述的屬性。
Object的defineProperty和defineProperties這兩個方法在js中的重要性十分重要,主要功能就是用來定義或修改這些內部屬性,與之相對應的getOwnPropertyDescriptor和getOwnPropertyDescriptors就是獲取這行內部屬性的描述。
下面文章我先介紹數據描述符和存取描述符的屬性代表的含義,然后簡單介紹以上四個方法的基本功能,這些如果了解可直接跳過,最后我會舉例擴展及說明各內部屬性在各種場景下產生的實際效果,那才是這篇文章的核心內容。本文章關于概念性的描述還是會盡量使用《javaScript高級教程》、MDN網站等概念,保證準確和易于大家理解,講解部分則結合個人理解和舉例說明。
數據(數據描述符)屬性數據屬性有4個描述內部屬性的特性
[[Configurable]]表示能否通過delete刪除此屬性,能否修改屬性的特性,或能否修改把屬性修改為訪問器屬性,如果直接使用字面量定義對象,默認值為true
[[Enumerable]]表示該屬性是否可枚舉,即是否通過for-in循環或Object.keys()返回屬性,如果直接使用字面量定義對象,默認值為true
[[Writable]]能否修改屬性的值,如果直接使用字面量定義對象,默認值為true
[[Value]]該屬性對應的值,默認為undefined
訪問器(存取描述符)屬性訪問器屬性也有4個描述內部屬性的特性
[[Configurable]]和數據屬性的[[Configurable]]一樣,表示能否通過delete刪除此屬性,能否修改屬性的特性,或能否修改把屬性修改為訪問器屬性,如果直接使用字面量定義對象,默認值為true
[[Enumerable]]和數據屬性的[[Configurable]]一樣,表示該屬性是否可枚舉,即是否通過for-in循環或Object.keys()返回屬性,如果直接使用字面量定義對象,默認值為true
[[Get]]一個給屬性提供 getter 的方法(訪問對象屬性時調用的函數,返回值就是當前屬性的值),如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認為 undefined
[[Set]]一個給屬性提供 setter 的方法(給對象屬性設置值時調用的函數),如果沒有 setter 則為 undefined。該方法將接受唯一參數,并將該參數的新值分配給該屬性。默認為 undefined
創建/修改/獲取屬性的方法 Object.defineProperty()功能:
方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 并返回這個對象。如果不指定configurable, writable, enumerable ,則這些屬性默認值為false,如果不指定value, get, set,則這些屬性默認值為undefined
語法: Object.defineProperty(obj, prop, descriptor)
obj: 需要被操作的目標對象
prop: 目標對象需要定義或修改的屬性的名稱
descriptor: 將被定義或修改的屬性的描述符
var obj = new Object(); Object.defineProperty(obj, "name", { configurable: false, writable: true, enumerable: true, value: "張三" }) console.log(obj.name) //張三Object.defineProperties()
功能:
方法直接在一個對象上定義一個或多個新的屬性或修改現有屬性,并返回該對象。
語法: Object.defineProperties(obj, props)
obj: 將要被添加屬性或修改屬性的對象
props: 該對象的一個或多個鍵值對定義了將要為對象添加或修改的屬性的具體配置
var obj = new Object(); Object.defineProperties(obj, { name: { value: "張三", configurable: false, writable: true, enumerable: true }, age: { value: 18, configurable: true } }) console.log(obj.name, obj.age) // 張三, 18Object.getOwnPropertyDescriptor()
功能:
該方法返回指定對象上一個自有屬性對應的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不需要從原型鏈上進行查找的屬性)
語法: Object.getOwnPropertyDescriptor(obj, prop)
obj: 需要查找的目標對象
prop: 目標對象內屬性名稱
var person = { name: "張三", age: 18 } var desc = Object.getOwnPropertyDescriptor(person, "name"); console.log(desc) 結果如下 // { // configurable: true, // enumerable: true, // writable: true, // value: "張三" // }Object. getOwnPropertyDescriptors()
功能:
所指定對象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對象。
語法: Object.getOwnPropertyDescriptors(obj)
obj: 需要查找的目標對象
var person = { name: "張三", age: 18 } var desc = Object.getOwnPropertyDescriptors(person, "name"); console.log(desc) //{ // configurable: true, // enumerable: true, // value: "張三", // writable: true //}各種場景下描述符屬性的的擴展示例講解 . configurable
如果設置configurable屬性為false,則不可使用delete操作符(在嚴格模式下拋出錯誤), 修改所有內部屬性值會拋出錯誤,在《javaScript高級教程中》說只可以改變writable的值,現在改變writable的值也會拋出錯誤
在對象中添加一個數據描述符屬性var person = {}; Object.defineProperty(person, "name", { configurable: false, value: "John" }) ; delete person.name // 嚴格模式下拋出錯誤 console.log(person.name) // "John" 沒有刪除 Object.defineProperty(person, "name", { configurable: true //報錯 }); Object.defineProperty(person, "name", { enumerable: 2 //報錯 }); Object.defineProperty(person, "name", { writable: true //報錯 }); Object.defineProperty(person, "name", { value: 2 //報錯 });
注意:
以上是最開始定義屬性描述符時,writabl默認為false,才會出現上述效果,如果writable定義為true, 則可以修改[[writable]]和[[value]]屬性值,修改另外兩個屬性值報錯
var obj = {}; Object.defineProperty(obj, "a", { configurable: false, writable: true, value: 1 }); Object.defineProperty(obj, "a", { // configurable: true, //報錯 // enumerable: true, //報錯 writable: false, value: 2 }); var d = Object.getOwnPropertyDescriptor(obj, "a") console.log(d); // { // value: 2, // writable: false, // }在對象中添加存取描述符屬性
var obj = {}; var aValue; //如果不初始化變量, 不給下面的a屬性設置值,直接讀取會報錯aValue is not defined var b; Object.defineProperty(obj, "a", { configurable : true, enumerable : true, get: function() { return aValue }, set: function(newValue) { aValue = newValue; b = newValue + 1 } }) console.log(b) // undefined console.log(obj.a) // undefined, 當讀取屬性值時,調用get方法,返回undefined obj.a = 2; // 當設置屬性值時,調用set方法,aValue為2 console.log(obj.a) // 2 讀取屬性值,調用get方法,此時aValue為2 console.log(b) // 3 再給obj.a賦值時,執行set方法,b的值被修改為2,額外說一句,vue中的計算屬性就是利用setter來實現的
注意:
1.getter和setter可以不同時使用,但在嚴格模式下只其中一個,會拋出錯誤
2.數據描述符與存取描述符不可混用,會拋出錯誤
var obj = {}; Object.defineProperty(obj, "a", { value: "a1", get: function() { return "a2" } });
3.全局環境下:
var a = 1; // a屬于window, 相當于window.a
讓我們來看看a的描述符屬性
var d = Object.getOwnPropertyDescriptor(window, "a"); console.log(d) // { // configurable: false, // value: 1, // writable: true, // enumerable: true // }
在來看一下另一種不適用var聲明的方式初始化a變量
a = 1; //a相當于window的一個屬性, window.a
再來看看此時a的描述符屬性
var d = Object.getOwnPropertyDescriptor(window, "a"); console.log(d) // { // configurable: true, // 此時configurable屬性值為true // value: 1, // writable: true, // enumerable: true // }
注意:
只有使用var, let等操作符才是定義變量,而不使用var,直接a=1;,這樣a的含義為window的一個屬性,并不是我們所說的變量的概念。使用 var定義的任何變量,其configurable屬性值都為false,定義對象也是一樣
var b = { name: "bbb" } var d = Object.getOwnPropertyDescriptor(window, "b"); console.log(d) // { // configurable: false // value: 1, // writable: true, // enumerable: true // }
但是這里需要說明的一點是,使用字面量定義的對象,該對象內部的屬性的數據描述符屬性都為true
var b = { name: "bbb" } var d = Object.getOwnPropertyDescriptor(b, "name"); console.log(d) // { // configurable: true // writable: true, // enumerable: true // value: "bbb" // }Writable
當writable為false(并且configurable為true),[[value]]可以通過defineeProperty修改, 但不能直接賦值修改
var obj = {}; Object.defineProperty(obj, "a", { configurable: true, enumerable: false, writable: false, value: 1 }); Object.defineProperty(obj, "a", { configurable: false, enumerable: true, writable: false , value: 2 }); var d = Object.getOwnPropertyDescriptor(obj, "a") console.log(d); // 結果如下 // { // value: 2, // writable: false, // enumerable: true, // configurable: false // } 但是如果直接復制修改 var obj = {} Object.defineProperty(obj, "a", { configurable: true, enumerable: false, writable: false, value: 1 }); obj.a=2; var d = Object.getOwnPropertyDescriptor(obj, "a") console.log(d); // 結果如下 // { // value: 1, // 沒有做出修改 // writable: false, // enumerable: true, // configurable: false // }Enumerable
直接上例子
var obj = {}; Object.defineProperties(obj, { a: { value: 1, enumerable: false }, b: { value: 2, enumerable: true }, c: { value: 3, enumerable: false } }) obj.d = 4; //等同于 //Object.defineProperty(obj, "d", { // configurable: true, // enumerable: true, // writable: true, // value: 4 //}) for(var key in obj) { console.log(key); // 打印一次b, 一次d, a和c屬性enumerable為false,不可被枚舉 } var arr = Object.keys(obj); console.log(arr); // ["b", "d"]get和set 簡易的數據雙向綁定
在線demo地址: http://www.sunzhaoye.com/demo...
html代碼:
input1=>
input2=>
我每次比input1的值加1=>
js代碼:
var oInput1 = document.getElementById("input1"); var oInput2 = document.getElementById("input2"); var oSpan = document.getElementById("span"); var obj = {}; Object.defineProperties(obj, { val1: { configurable: true, get: function() { oInput1.value = 0; oInput2.value = 0; oSpan.innerHTML = 0; return 0 }, set: function(newValue) { oInput2.value = newValue; oSpan.innerHTML = Number(newValue) ? Number(newValue) : 0 } }, val2: { configurable: true, get: function() { oInput1.value = 0; oInput2.value = 0; oSpan.innerHTML = 0; return 0 }, set: function(newValue) { oInput1.value = newValue; oSpan.innerHTML = Number(newValue)+1; } } }) oInput1.value = obj.val1; oInput1.addEventListener("keyup", function() { obj.val1 = oInput1.value; }, false) oInput2.addEventListener("keyup", function() { obj.val2 = oInput2.value; }, false)總結
終于到了最后了,就不具體梳理總結了。雖然我們在開過過程中不怎么使用幾種方法,但理解之后對于我們理解js中對象有很大幫助,對后續進步也很有幫助,比如vue的實現原理等。個人能力有限,還希望大家發現問題后能多多指點,共同進步。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88578.html
摘要:與當與同時為時,屬性不能重新使用定義,嚴格模式下會報錯示例云麒報錯當或者為時,屬性可以重新使用定義,這一點讀者不妨自行測試。 摘要: JavaScript有個很神奇的Object.defineProperty(),了解一下? =與Object.defineProperty 為JavaScript對象新增或者修改屬性,有兩種不同方式:直接使用=賦值或者使用Object.definePro...
摘要:返回值被傳遞給函數的對象。描述該方法允許精確添加或修改對象的屬性。描述符必須是兩種形式之一不能同時是兩者。可以是任何有效的值數值,對象,函數等。該方法返回值被用作屬性值。該方法將接受唯一參數,并將該參數的新值分配給該屬性。 Object.defineProperties() Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性...
摘要:枚舉對象的屬性第二種情況設置為,可以被枚舉。內置對象訪問器屬性方法介紹摘自方法返回指定對象上一個自有屬性對應的屬性描述符。對象中存在的屬性描述符主要有數據描述符和訪問器描述符兩種返回傳遞給函數的對象參考中的 1. 什么是對象 對象是無序屬性的集合 創建自定義對象最簡單的方式就是以字面量的形式創建對象(或創建一個Object實例),然后再為它添加屬性和方法,如下所示: var perso...
摘要:深入理解中的屬性和特性中屬性和特性是完全不同的兩個概念,這里我將根據自己所學,來深入理解中的屬性和特性。其中第三個參數描述符對象是對象字面量的方法創建的,里面的屬性和屬性值實際上保存的是要修改的特性和特性值。 深入理解JavaScript中的屬性和特性 JavaScript中屬性和特性是完全不同的兩個概念,這里我將根據自己所學,來深入理解JavaScript中的屬性和特性。 主...
摘要:一旦目標對象訪問該屬性,就會調用這個方法,并返回結果。如果為,則任何嘗試刪除目標屬性或修改屬性以下特性的行為將被無效化,默認為。語法參數目標對象要為目標對象添加的屬性,其中和分別代表中的第二和第三個參數。 Object.defineProperty The Object.defineProperty() method defines a new property directly on...
閱讀 3616·2021-11-24 10:22
閱讀 3686·2021-11-22 09:34
閱讀 2480·2021-11-15 11:39
閱讀 1528·2021-10-14 09:42
閱讀 3662·2021-10-08 10:04
閱讀 1553·2019-08-30 15:52
閱讀 847·2019-08-30 13:49
閱讀 3015·2019-08-30 11:21