Examplevue
var person = {name:''}; var personCopy = new Proxy(person,{ get(target,key,receiver){ console.log('get方法被拦截。。。'); return Reflect.get(target,key,receiver); }, set(target,key,value,receiver){ console.log('set方法被拦截。。。') return Reflect.set(target,key,value,receiver); } }) person.name = 'arvin'; // 未有拦截日志打出 personCopy.name = 'arvin'; // set方法被拦截。。。 console.log(person.name); // 未有拦截日志打出 console.log(personCopy.name); // get方法被拦截。。。
代码解读:从上述的例子能够看出,被代理对象person的get和set不会通过代理拦截器get,set,而只有代理对象personCopy在get和set方法调用的时候才会通过拦截器,因而可知ES6的代理Proxy并非一个相似JAVA的AOP,而其实只是将person的引用赋值给了personCopy,让代理对象personCopy和被代理对象person指向了同一个内存空间,下面是我实现的一个用ES5写的Proxy拦截,供你们参考理解Proxy实现原理提供思路:工具
Example:this
/**浅拷贝工具方法**/ function clone(myObj){ if(typeof(myObj) != 'object' || myObj == null) return myObj; var newObj = new Object(); for(var i in myObj){ newObj[i] = clone(myObj[i]); } return newObj; } /*代理实现类*/ function ProxyCopy(target,handle){ var targetCopy = clone(target); Object.keys(targetCopy).forEach(function(key){ Object.defineProperty(targetCopy, key, { get: function() { return handle.get && handle.get(target,key); }, set: function(newVal) { handle.set && handle.set(); target[key] = newVal; } }); }) return targetCopy; } var person = {name:''}; var personCopy = new ProxyCopy(person,{ get(target,key){ console.log('get方法被拦截。。。'); return target[key]; }, set(target,key,value){ console.log('set方法被拦截。。。') // return true; } }) person.name = 'arvin'; // 未有拦截日志打出 personCopy.name = 'arvin'; // set方法被拦截。。。 console.log(person.name); // 未有拦截日志打出 console.log(personCopy.name); // get方法被拦截。。。
要说到ES5的代理实现,其中比较有名的就算是vue的双向绑定中到了get和set的代理拦截实现了,下面是一个仿照该技术的一个实现:prototype
Example双向绑定
// 拦截器 function Observer(data) { this.data = data; this.walk(data); } (function($Observer){ $Observer.prototype = { walk: function(data) { var me = this; Object.keys(data).forEach(function(key) { me.convert(key, data[key]); }); }, convert: function(key, val) { this.defineReactive(this.data, key, val); }, defineReactive: function(data, key, val) { var childObj = observe(val); Object.defineProperty(data, key, { enumerable: true, // 可枚举 configurable: false, // 不能再define get: function() { return val; }, set: function(newVal) { if (newVal === val) { return; } val = newVal; console.log("新的值是object的话,进行监听"); console.log("通知订阅者"); dep.notify(); } }); } }; })(Observer); // 拦截器的出口 function observe(value) { if (!value || typeof value !== 'object') { return; } return new Observer(value); };