The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).MDN Proxyvue
MDN表述该对象构造器是用于对某对象定义用户自定义行为的。那么,这究竟是什么意思呢?咱们下面直接来分析一下Vue源码中应用到Proxy对象的地方,来理解该对象构造器的做用。react
首先咱们来看一看Vue源码的 1430行git
/* not type checking this file because flow doesn't play well with Proxy */ var initProxy; { var allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify ); var warnNonPresent = function(target, key) { warn( "Property or method \"" + key + "\" is not defined on the instance but " + "referenced during render. Make sure to declare reactive data " + "properties in the data option.", target ); }; var hasProxy = typeof Proxy !== 'undefined' && Proxy.toString().match(/native code/); if (hasProxy) { var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); config.keyCodes = new Proxy(config.keyCodes, { set: function set(target, key, value) { if (isBuiltInModifier(key)) { warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key)); return false } else { target[key] = value; return true } } }); } var hasHandler = { has: function has(target, key) { var has = key in target; var isAllowed = allowedGlobals(key) || key.charAt(0) === '_'; if (!has && !isAllowed) { warnNonPresent(target, key); } return has || !isAllowed } }; var getHandler = { get: function get(target, key) { if (typeof key === 'string' && !(key in target)) { warnNonPresent(target, key); } return target[key] } }; initProxy = function initProxy(vm) { if (hasProxy) { // determine which proxy handler to use var options = vm.$options; var handlers = options.render && options.render._withStripped ? getHandler : hasHandler; vm._renderProxy = new Proxy(vm, handlers); } else { vm._renderProxy = vm; } }; }
首先,咱们要明白一件事情,vue放弃了对ie9如下的支持。即便这样,因为Proxy做为一个es6的新特性,支持度依然不高,做者也只是尝试着使用了一下。下面咱们来一步一步讲解。es6
var allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify );
该处定义了所容许的全局对象类型。github
var warnNonPresent = function(target, key) { warn( "Property or method \"" + key + "\" is not defined on the instance but " + "referenced during render. Make sure to declare reactive data " + "properties in the data option.", target ); };
该处定义了一个报警方法,传入键名或方法名,log显示一条警告app
var hasProxy = typeof Proxy !== 'undefined' && Proxy.toString().match(/native code/);
该处是对es6特性Proxy的检测, 其检测手段是确认Proxy是原生实现并未被用户代码所覆盖。函数
var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); config.keyCodes = new Proxy(config.keyCodes, { set: function set(target, key, value) { if (isBuiltInModifier(key)) { warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key)); return false } else { target[key] = value; return true } } });
该段代码对config.keyCodes对象进行了代理,其意义在于禁止用户修改Vue内建的一些按键值,这些按键值和按键名是对应的。若是用过Vue的用户应该知道,Vue在事件对象上对一些经常使用按键和经常使用操做进行了内建(这个内建过程被用eval函数压缩了,由一堆代码段构成的,没什么看头),做者确定不但愿也不容许用户修改配置的时候覆盖了内建内容。因而,当咱们作config.keyCodes['stop'] = xxx这样的操做的时候,Vue就会告诉你说“你这我的,不老实,为何想着改我东西”,直接打出禁止改写内建配置的警告。若是非内建内容,那么能够直接设置上。ui
initProxy = function initProxy(vm) { if (hasProxy) { // determine which proxy handler to use var options = vm.$options; var handlers = options.render && options.render._withStripped ? getHandler : hasHandler; vm._renderProxy = new Proxy(vm, handlers); } else { vm._renderProxy = vm; } };
这句话就再也不解释了,相似上面。不过读者可能会问has是什么? 那么下面咱们来说解一下Proxy的各个参数this
两个, var b = new Proxy(a, { has: fn xxx, get: fn xxx, set: fn xxx .... })代理
target 被代理的对象
handler 处理器对象
用来定义咱们对该对象的各类操做
完整的handler处理器对象内容:
{ get: '咋获取', set: '咋设置', deleteProperty: '咋删除', enumerate: '咋枚举', ownKeys: '咋获取全部该对象的属性键 ', has: '问你有没有, 好比 "xxx" in target', defineProperty: '如何defineProperty, 这个咱们也是能够代理的', getOwnPropertyDescriptor: '获取属性描述的代理', getPrototypeOf: '找原型时候的代理', setPrototypeOf: '设置对象原型的时候的代理', isExtensible: '判断对象是否可扩展的时候的代理', preventExtensions: '设置阻止对象扩展的时候的代理', apply: '执行调用操做的时候的代理', construct: '执行实例化的时候的代理' }
以上皆是函数~~
拦截,预警,上报,扩展功能,统计,强化对象...能想获得的都能沾到点边,这里Vue的代码主要将代理运用于拦截。而且因为规范依然在发展,因此你们慎用。。。