以前有了解到 Object.defineProperty
方法,可以在對象獲取值或者設置值的時候進行一些操做,且 Vue.js 的雙向綁定,也是經過這個方法實現的,因此如今以爲有必要深刻的瞭解一番。javascript
首先,先看看 Object.defineProperty
的基礎用法,這個方法接收三個參數:java
其中,描述符(descriptor)對象的屬性必須是:函數
delete
刪除屬性從而從新定義,可否修改屬性的特性,或者可否把屬性修改成訪問器屬性,默認值爲 false
。for-in
循環返回屬性,默認值爲 false
。false
。value
值,當咱們讀取屬性值的時候,就是從這個位置讀,當咱們給屬性賦值時,也是從這個位置寫入,不一樣於上面的屬性,這個屬性的默認值是 undefined
。undefine
。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
方法時,若是不指定, configurable
、 enumerable
、 writable
特性的默認值都是 false
。對象
這裏面要重點說一下 get
和 set
屬性,看下面的例子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
設置了 get
和 set
函數。 get
函數返回 _name
值 JavaScript
, set
函數經過判斷傳入的新值 newValue
是否等於 _name
值,若是不等於則會給 _name
、 author
、 birth
從新賦值。
因爲爲對象定義多個屬性的可能性很大, 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
。