Object.defineProperty 方法學習

以前有了解到 Object.defineProperty 方法,可以在對象獲取值或者設置值的時候進行一些操做,且 Vue.js 的雙向綁定,也是經過這個方法實現的,因此如今以爲有必要深刻的瞭解一番。javascript

首先,先看看 Object.defineProperty 的基礎用法,這個方法接收三個參數:java

  1. 屬性所在對象
  2. 屬性的名字
  3. 描述符對象(descriptor)

其中,描述符(descriptor)對象的屬性必須是:函數

  1. configurable: 表示可否經過 delete 刪除屬性從而從新定義,可否修改屬性的特性,或者可否把屬性修改成訪問器屬性,默認值爲 false
  2. enumerable: 表示可否經過 for-in 循環返回屬性,默認值爲 false
  3. writable: 表示可以修改屬性的值,默認值同爲 false
  4. value: 這個屬性的數據值,就是咱們常說的 value 值,當咱們讀取屬性值的時候,就是從這個位置讀,當咱們給屬性賦值時,也是從這個位置寫入,不一樣於上面的屬性,這個屬性的默認值是 undefined
  5. get: 在讀取屬性時調用的函數,默認值爲 undefine
  6. set:在寫入屬性時調用的函數,默認值爲 undefine

舉個例子ui

var language = {}
Object.defineProperty(language, 'name', {
  writable: false,
  value: 'JavaScript'
})
console.log(language.name); // JavaScript
language.name = 'PHP';
cosnole.log(language.name); // JavaScript
複製代碼

以上代碼中建立了一個 language ,並定義了屬性爲 name ,值爲 JavaScript 的只讀對象。這個屬性的值是不可修改的,若是對這個屬性進行從新賦值,在非嚴格模式下,賦值操做會被忽略;在嚴格模式下,賦值操做會致使程序拋出錯誤。this

相似的操做也不適用 configurable 屬性,例如spa

var language = {}
Object.defineProperty(language, 'name', {
  configurable: false,
  value: 'JavaScript'
})
console.log(language.name); // JavaScript
delete language.name;
cosnole.log(language.name); // JavaScript
複製代碼

以上代碼中建立了一個 language ,並定義了屬性爲 name ,值爲 JavaScript 的不可配置對象。這個屬性是不可配置的,若是對這個屬性進行刪除處理,在非嚴格模式下,刪除操做會被忽略;在嚴格模式下,刪除操做會致使程序拋出錯誤。雙向綁定

不一樣於 writable ,一旦設置屬性的 configurable 的值爲 false , 就不能再更改成 true 了,若是嘗試這樣操做也會致使程序報錯。code

在調用 Object.defineProperty 方法時,若是不指定, configurableenumerablewritable 特性的默認值都是 false對象

這裏面要重點說一下 getset 屬性,看下面的例子ip

var language = {
  _name: 'JavaScript',
  author: 'Brendan Eich',
  birth: 1995
}

Object.defineProperty(language, "name", {
  get: function () {
    return this._name;
  },
  set: function ( newValue ) {
    if ( newValue !== this._name) {
      this._name = 'this is not ' + this._name;
      this.author = null;
      this.birth = 0000;
    }
  }
})

console.log(language.name); // JavaScript
language.name = 'PHP';
console.log(language.name); // this is not JavaScript
複製代碼

從以上代碼能夠看出,經過 Object.defineProperty 給對象 language 建立了新屬性 name ,而 name 設置了 getset 函數。 get 函數返回 _nameJavaScriptset 函數經過判斷傳入的新值 newValue 是否等於 _name 值,若是不等於則會給 _nameauthorbirth 從新賦值。

因爲爲對象定義多個屬性的可能性很大, ECMAScript5 又定義了一個 Object.defineProperties 方法,利用這個方法能夠經過描述符一次定義多個屬性,如下爲使用例子

var language = {}
Object.defineProperties(language, {
  _name: {
    writable: true,
    value: 'JavaScript'
  },
  year: {
    writable: true,
    value: 1995
  },
  author: {
    writable: true,
    value: 'Brendan Eich'
  },
  name: {
    get: function () {
      return this._name;
    },
    set: function ( newValue ) {
      if ( newValue !== this._name) {
        this._name = 'this is not ' + this._name;
        this.author = null;
        this.birth = 0000;
      }
    }
  }
})
複製代碼

這裏須要說明的是,在定義屬性時,若是這個值是須要改變的,須要加上 writable: true 才行,要不屬性的的默認 writable 是爲 false

相關文章
相關標籤/搜索