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

相关文章
相关标签/搜索