JavaScript的Object.defineProperty()属性

 

Object.defineProperty(obj, prop, descriptor)

 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

参数

  • obj 目标对象
  • prpo 属性值(目标对象存在该属性时,进行修改,不存在时进行创建)
  • descriptor  对属性的描述,可选配置如下:
  1. configurable:默认值为false, 为true时,该属性的descriptor才能够被改变, 同时也能够被删除
  2. enumerable: 默认false, 为true时, 该属性才会出现再对象的枚举属性中
  3.  value:属性值
  4. writable: false时,value值不可写
  5. get: 属性的 getter 函数,如没有则为 undefined,访问拦截器,
  6. set: 属性的 setter 函数,如果没有则为 undefined, 修改拦截器

 在 get 和 set 方法中,this 指向某个被访问和修改属性的对

var obj = {};
 obj.b = 1;
 // 等同于:
 Object.defineProperty(obj, "b", {
   value: 1,
   writable: true,
   configurable: true,
   enumerable: true
 });
 // 另一方面,
 Object.defineProperty(obj, "a", { value : 2 });
 // 等同于:
 Object.defineProperty(obj, "a", {
   value: 2,
   writable: false,
   configurable: false,
   enumerable: false
 });
// set get 方法
 function Archiver() {
    var temperature = null;
    var archive = [];
    Object.defineProperty(this, 'temperature', {
      get: function() {
        console.log('get!');
        return temperature;
      },
      set: function(value) {
        temperature = value;
        archive.push({ val: temperature });
      }
    });
    this.getArchive = function() { return archive; };
  }

  var arc = new Archiver();
  arc.temperature; // 'get!'
  arc.temperature = 11;
  arc.temperature = 13;
  console.log(arc.getArchive()); // [{ val: 11 }, { val: 13 }]

 

vue2 实现双向绑定

Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更新

/**
 * 把一个对象的每一项都转化成可观测对象
 * @param { Object } obj 对象
 */

function observable (obj) {
    if (!obj || typeof obj !== 'object') {
        return;
    }
    let keys = Object.keys(obj);
    keys.forEach((key) =>{
        defineReactive(obj,key,obj[key])
    })
    return obj;
}
/**
 * 使一个对象转化成可观测对象
 * @param { Object } obj 对象
 * @param { String } key 对象的key
 * @param { Any } val 对象的某个key的值
 */
function defineReactive (obj,key,val) {
    Object.defineProperty(obj, key, {
        get(){
            console.log(`${key}属性被读取了`);
            return val;
        },
        set(newVal){
            console.log(`${key}属性被修改了`);
            val = newVal;
        }
    })
}
let car = observable({
    'brand':'BMW',
    'price':3000
})
car.price; // price属性被读取了
car.price = 4000; // price属性被修改了

参考:

https://my.oschina.net/u/4386652/blog/4281447

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

你可能感兴趣的:(JavaScript)