目标:如何监听对象的属性的读取和变化
参考文献:https://github.com/youngwind/blog/issues/84
第一:当对象的某个属性变化的时候,如何触发自定义的回调函数?
答案:ES5中新添加了一个方法:Object.defineProperty,通过这个方法,可以自定义getter和setter函数,从而在获取对象属性和设置对象属性的时候能够执行自定义的回调函数。
Object.defineProperty(obj, prop, descriptor)方法接收三个参数:需要添加或修改属性的对象,属性名称,属性描述options。
Object.defineProperty(app1,'name',{ enumerable: true, //是否是可配置的 configurable: true,//枚举 get:function(){ console.log("你访问了name"); }, set:function(newVal){ if(val === newVal) return; val = newVal; } });
//new Observer构造函数 function Observer(data){ this.data = data; this.walk(data) } let p =Observer.prototype; //遍历对象的各个属性,为所有对象绑定getter和setter, p.walk = function(obj){ let val; // hasOwnProperty() 方法会返回一个布尔值,其用来判断某个对象是否含有指定的属性 //因为for...in 循环会把对象原型链上的所有可枚举属性都循环出来,所以需要hasOwnProperty进行过滤 for(let key in obj){ if(obj.hasOwnProperty(key)){ val = obj[key]; //判断是否遍历到最底层,否的话继续遍历 if(typeof val === 'object'){ new Observer(val); } //到这一步获取了属性和值 this.convert(key,val); } } }; // convert函数对getter和setter函数进行的详细设置 p.convert = function(key,val){ Object.defineProperty(this.data,key,{ enumerable:true, configurable:true, get:function(){ console.log('你访问了'+key); return val }, set:function(newVal){ console.log('你设置了'+key); console.log('新的'+key+'为'+newVal) if(newVal===val) return; val = newVal } }) }; let data ={ a:{ name: 'youngwind', age: '25' }, b:{ university: 'bupt', major: 'computer' } }; let app1 = new Observer(data.a); let app2 = new Observer(data.b);
注:let 如果不能运行的话,设置为严格模式,在第一行加"use strict";