以前有了解到 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
。