1. 程式人生 > >javascript中數據屬性和訪問器屬性

javascript中數據屬性和訪問器屬性

創建 ron 利用 就會 {} 嚴格模式 enum 使用 str

1.屬性

  ECMAScript中有兩種屬性:數據屬性和訪問器屬性。

  一、數據屬性

  數據屬性包含一個數據值的位置,在這個位置可以讀取和寫入值。

  var person = { name :"Nicholas" };

  要修改屬性默認的特性,必須使用ECMAScript 5 的Object.defineProperty()方法,這個方法接收3個參數:屬性所在的對象,屬性的名字和一個描述符對象。其中,描述符(descriptor)對象的屬性必須是:configurable、enumerable、writable 和 value。設置其中的一或多個值,可以修改對應的特性值。例如: 

  var person = {};
  Object.defineProperty(person, "name", {
    writable: false,
    value: "Nicholas"
  });
  alert(person.name); //"Nicholas"
  person.name = "Greg";
  alert(person.name); //"Nicholas"

  這個例子創建了一個名為 name 的屬性,它的值"Nicholas"是只讀的。這個屬性的值是不可修改的,如果嘗試為它指定新值,則在非嚴格模式下,賦值操作將被忽略;在嚴格模式下,賦值操作將會導致拋出錯誤。

  類似的規則也適用於不可配置的屬性。例如:

  var person = {};
  Object.defineProperty(person, "name", {
    configurable: false,
    value: "Nicholas"
  });
  alert(person.name); //"Nicholas"
  delete person.name;
  alert(person.name); //"Nicholas"

  把 configurable 設置為 false,表示不能從對象中刪除屬性。如果對這個屬性調用 delete,則在非嚴格模式下什麽也不會發生,而在嚴格模式下會導致錯誤。而且,一旦把屬性定義為不可配置的,就不能再把它變回可配置了。此時,再調用 Object.defineProperty()方法修改除 writable 之外的特性,都會導致錯誤:  var person = {};   Object.defineProperty(person, "name", {

    configurable: false,
    value: "Nicholas"
  });
  //拋出錯誤
  Object.defineProperty(person, "name", {
    configurable: true,
    value: "Nicholas"
  });
  也就是說,可以多次調用 Object.defineProperty()方法修改同一個屬性,但在把 configurable
特性設置為 false 之後就會有限制了。

  在調用 Object.defineProperty()方法時,如果不指定,configurable、enumerable 和writable 特性的默認值都是 false。多數情況下,可能都沒有必要利用 Object.defineProperty()方法提供的這些高級功能。不過,理解這些概念對理解 JavaScript 對象卻非常有用。

  二、訪問器屬性

  訪問器屬性不包含數據值;它們包含一對兒 getter 和 setter 函數(不過,這兩個函數都不是必需的)。  

  在讀取訪問器屬性時,會調用 getter 函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter 函數並傳入新值,這個函數負責決定如何處理數據。訪問器屬性有如下 4 個特性。

    ? [[Configurable]]:表示能否通過 delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為數據屬性。對於直接在對象上定義的屬性,這個特性的默認值為true。

    ? [[Enumerable]]:表示能否通過 for-in 循環返回屬性。對於直接在對象上定義的屬性,這個特性的默認值為 true。

    ? [[Get]]:在讀取屬性時調用的函數。默認值為 undefined。
    ? [[Set]]:在寫入屬性時調用的函數。默認值為 undefined。
  訪問器屬性不能直接定義,必須使用 Object.defineProperty()來定義。請看下面的例子:

  var book = {

    _year: 2004,
    edition: 1
  };
  Object.defineProperty(book, "year", {
    get: function(){
      return this._year;
    },
    set: function(newValue){
      if (newValue > 2004) {
        this._year = newValue;
        this.edition += newValue - 2004;
      }
    }
  });
  book.year = 2005;
  alert(book.edition); //2

  以上代碼創建了一個 book 對象,並給它定義兩個默認的屬性:_year 和 edition。_year 前面的下劃線是一種常用的記號,用於表示只能通過對象方法訪問的屬性。而訪問器屬性 year 則包含一個getter 函數和一個 setter 函數。getter 函數返回_year 的值,setter 函數通過計算來確定正確的版本。因此,把 year 屬性修改為 2005 會導致_year 變成 2005,而 edition 變為 2。這是使用訪問器屬性的常見方式,即設置一個屬性的值會導致其他屬性發生變化。

  不一定非要同時指定 getter 和 setter。只指定 getter 意味著屬性是不能寫,嘗試寫入屬性會被忽略。在嚴格模式下,嘗試寫入只指定了 getter 函數的屬性會拋出錯誤。類似地,只指定 setter 函數的屬性也不能讀,否則在非嚴格模式下會返回 undefined,而在嚴格模式下會拋出錯誤。

  支持 ECMAScript 5 的這個方法的瀏覽器有 IE9+(IE8 只是部分實現)、Firefox 4+、Safari 5+、Opera 12+ 和 Chrome 。在這個方法之前,要創建訪問器屬性,一般都使用兩個非標準的方法:__defineGetter__()和__defineSetter__()。這兩個方法最初是由 Firefox 引入的,後來 Safari 3、Chrome 1 和 Opera 9.5 也給出了相同的實現。使用這兩個遺留的方法,可以像下面這樣重寫前面的例子。

  var book = {
    _year: 2004,
    edition: 1
  };
  //定義訪問器的舊有方法
  book.__defineGetter__("year", function(){
    return this._year;
  });
  book.__defineSetter__("year", function(newValue){
    if (newValue > 2004) {
      this._year = newValue;
      this.edition += newValue - 2004;
    }
  });
  book.year = 2005;
  alert(book.edition); //2

  在不支持Object.defineProperty()方法的瀏覽器中不能修改[[Configurable]]和[[Enumerable]]。

javascript中數據屬性和訪問器屬性