《js高级程序设计》6.1.1-6.1.3——数据属性、访问器属性
數據屬性:該屬性包含了一個數據值的位置,它包含了4個描述行為的特性:
1. [[Configurable]]:表示是否能通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,能否把屬性修改為訪問器屬性。
2. [[Enumerable]]:表示能否用for-in循環返回。
3. [[writable]]:表示能否修改屬性的值。
4. [[Value]]:包含這個屬性的數據值。讀取屬性值的時候從這個位置讀,寫入屬性值的時候更新到這個位置,默認值為undefined。
直接在對象上定義的屬性的數據特性默認如下:
1. [[Configurable]]:true
2. [[Enumerable]]:true
3. [[writable]]:true
4. [[Value]]:”xiaochang” (初始時的賦值)
這些特性不能直接被訪問,要修改屬性的特性只能通過Object.defineProperty( )方法,該方法包含三個參數:屬性所在的對象,屬性的名字,描述符對象[configurable|enumerable|writable|value]。例如:
var person = {age:100 };Object.defineProperty(person,"name",{configurable:false,writable:false,value:"xiaochang" });Object.defineProperty(person,"tall",{value:160 });for(attr in person){console.log(attr); //name,age } console.log(person.name); //xiaochang person.name="CC"; //為name屬性指定新值 console.log(person.name); //xiaochang delete person.name; //刪除name屬性 console.log(person.name); //xiaochangconsole.log(person.age); //100 person.age=200; //為age屬性指定新值 console.log(person.age); //200 delete person.age; //刪除age屬性 console.log(person.age); //undefinedconsole.log(person.tall); //160 person.tall = 160; //修改tall屬性的值 console.log(person.tall); //160 delete person.tall; //刪除name屬性 console.log(person.tall); //160 分析例子可知直接在對象上定義的屬性,如age,[[Configurable]],[[Enumerable]],[[writable]]都被設置為true。
屬性name的[[Configurable]],[[writable]]被設置為false,所以無法修改和刪除。
調用Object.defineProperty( )方法時,如果不顯示指定configurable,enumerable,writable的值,就默認為false,如屬性tall。
另外需要注意的是當configurable設置為false后無法再將其改為true,且除了writable之外,無法修改其它特性。在configurable為true的情況下可多次調用Object.defineProperty( )修改同一屬性。
在非嚴格情況下修改無法配置的屬性操作會被忽略,在嚴格模式下會拋出錯誤。
訪問器屬性:包含getter和setter函數。讀取訪問器屬性時,調用getter函數,返回有效的值;在寫入訪問器屬性時,調用setter函數傳入新值。它包含了4個特性:
1. [[Configurable]]:表示是否能通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,能否把屬性修改為訪問器屬性。
2. [[Enumerable]]:表示能否用for-in循環返回。
3. [[Get]]:讀取屬性時調用的函數,默認undefined。
4. [[Set]]:寫入屬性時調用的函數,默認undefined。
getter和setter不一定要成對出現,只有getter函數證明該屬性只讀不可寫,嘗試寫入在非嚴格模式下會被忽略,嚴格模式會拋出錯誤。相同,只有setter函數證明只寫不能讀,嘗試讀在非嚴格模式下返回undefined,嚴格模式則拋出錯誤。
訪問器屬性無法直接定義,必須使用Object.defineProperty( )來定義,如下:
var person = {_name:"xiaochang", //name屬性只讀不可寫_age:100, //age屬性只寫不可讀_tel:123456 //tel屬性可讀可寫 }; Object.defineProperty(person,"name",{get:function(){return this._name;} }); Object.defineProperty(person,"age",{set:function(newage){this._age = newage;} }); Object.defineProperty(person,"tel",{get:function(){return this._tel;},set:function(newtel){this._tel= newtel;} }); console.log(person.name); //"xiaochang" person.name = "CC"; //嘗試修改name屬性 console.log(person.name); //"xiaochang" console.log(person.age); //不可讀屬性,undefined person.age = 200; //修改age console.log(person._age); //直接讀取對象方法才能訪問的屬性,可以看到值已更新200 console.log(person.tel); //123456 person.age = 654321; //更新tel console.log(person.tel); //654321
屬性前面的下劃線表示只能通過對象方法訪問的屬性,當我們調用person.name時實際調用了name屬性的getter函數(直接調用person._name可得到相同的結果,這樣做訪問器就沒什么意義了)。通過上面例子中可以很清晰的看出屬性與訪問器之間的關系。
支持Object.defineProperty( )方法的瀏覽器有IE9+(IE8是第一實現Object.defineProperty( )方法的瀏覽器,但僅限于DOM對象,且只能創建訪問器屬性)、Firefox4+、Safari5+,Opera12+、Chrome。在不支持Object.defineProperty( )方法的瀏覽器中不能修改[[Configurable]],[[Enumerable]]。
在Object.defineProperty( )方法之前,要創建訪問器屬性,一般使用非標準的方法:__defineGetter__()?和__defineSetter__(),這兩個方法最初在Firefox引入,后來chrome1和Opera9.5也支持。改寫上面的tel屬性訪問器如下:
person.__defineGetter__("tel",function(){return this._tel; }); person.__defineSetter__("tel",function(newtel){this._tel = newtel;ECMAScript 5還定義Object.defineProperties( )方法,該方法包含兩個參數:屬性所在的對象,多個屬性的名字和其描述符對象組成的對象。其作用于Object.defineProperty( )相同,區別是可一次性定于多個屬性。支持該方法的瀏覽器有IE9+、Firefox4+、Safari5+,Opera12+、Chrome。上面的例子可以改寫如下:
var person = {_name:"xiaochang", //name屬性只讀不可寫_age:100, //age屬性只寫不可讀_tel:123456 //tel屬性可讀可寫 }; Object.defineProperties(person,{name:{get:function(){return this._name;}},age:{set:function(newage){this._age = newage;}},tel:{get:function(){return this._tel;},set:function(newtel){this._tel= newtel;}} });對于上述講到的屬性特性,ECMAScript 5 給出了可以取得給定屬性的描述符的方法Object.getOwnPropertyDescriptor(),該方法包含兩個參數:屬性所在的對象,要讀取其描述符的屬性名稱。方法返回一個對象。如針對上面的例子可得:
var descriptor = Object.getOwnPropertyDescriptor(person,"tel"); for(attr in descriptor ){console.log(attr+":"+descriptor[attr]); }運行結果如下: get:function (){return this._tel;} set:function (newtel){this._tel= newtel;} enumerable:false configurable:false原文:http://www.2cto.com/kf/201504/393319.html
轉載于:https://www.cnblogs.com/mmlvj/p/4664071.html
總結
以上是生活随笔為你收集整理的《js高级程序设计》6.1.1-6.1.3——数据属性、访问器属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《学习opencv》笔记——矩阵和图像处
- 下一篇: 新地王的诞生终将付出惨痛的代价?