JavaScript--資料屬性和訪問器屬性

來源:互聯網
上載者:User

JavaScript--資料屬性和訪問器屬性

   在JavaScript中最基本的建立一個對象的方法是new一個Object()的執行個體,然後再為其添加屬性與方法,下例建立一個包含屬性name的person對象,name屬性的特徵值為”xiaochang”:

  var person = new Object();person.name = "xiaochang";person.say = function(){ console.log("Hi, my name is " + this.name);};person.say(); //Hi, my name is xiaochang

  EAMAScript. 5 定義了描述這些屬性特徵的各類特性,包括資料屬性和訪問器屬性。

  資料屬性:該屬性包含了一個資料值的位置,它包含了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); //xiaochangperson.name="CC"; //為name屬性指定新值console.log(person.name); //xiaochangdelete person.name; //刪除name屬性console.log(person.name); //xiaochangconsole.log(person.age); //100person.age=200; //為age屬性指定新值console.log(person.age); //200delete person.age; //刪除age屬性console.log(person.age); //undefinedconsole.log(person.tall); //160person.tall = 160; //修改tall屬性的值console.log(person.tall); //160delete 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( )修改同一屬性。

  在非嚴格情況下修改無法配置的屬性操作會被忽略,在strict 模式下會拋出錯誤。

  訪問器屬性:包含getter和setter函數。讀取存取器屬性時,調用getter函數,返回有效值;在寫入訪問器屬性時,調用setter函數傳入新值。它包含了4個特性:

  1. [[Configurable]]:表示是否能通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,能否把屬性修改為訪問器屬性。

  2. [[Enumerable]]:表示能否用for-in迴圈返回。

  3. [[Get]]:讀取屬性時調用的函數,預設undefined。

  4. [[Set]]:寫入屬性時調用的函數,預設undefined。

  getter和setter不一定要成對出現,只有getter函數證明該屬性唯讀不可寫,嘗試寫入在非strict 模式下會被忽略,strict 模式會拋出錯誤。相同,只有setter函數證明唯寫不能讀,嘗試讀在非strict 模式下返回undefined,strict 模式則拋出錯誤。

  訪問器屬性無法直接定義,必須使用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); //不可讀屬性,undefinedperson.age = 200; //修改ageconsole.log(person._age); //直接讀取對象方法才能訪問的屬性,可以看到值已更新200console.log(person.tel); //123456person.age = 654321; //更新telconsole.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:falseconfigurable:false

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.