var proxies = {}; proxies.config = {}; proxies.config.start = true; // 是否启动拦截 proxies.config.get = true; // 是否拦截获取 proxies.config.set = true; // 是否拦截设置 proxies.config.apply = false; // 是否拦截函数执行 proxies.config.getOwnPropertyDescriptor = false; // 是否拦截获取自己的属性描述符 proxies.config.defineProperty = false; // 是否拦截定义属性 proxies.config.construct = false; proxies.config.deleteProperty = false; proxies.config.has = false; proxies.config.ownKeys = false; proxies.config.getPrototypeOf = false; proxies.config.setPrototypeOf = false; proxies.config.preventExtensions = false; proxies.config.isExtensible = false; proxies.config.index = 0 proxies.get_type = function (data) { return Object.prototype.toString.call(data); }; proxies.proxy = function proxy(obj, objName) { //obj:原始对象 //objName:原始对象的名字 if (!proxies.config.start) { console.log('代理已关闭'); return obj } let handler = { get: function (target, prop, receiver) {//三个参数 //target: 原始对象 这里是user //属性:属性 只有string和symbol两个类型 //receiver:代理后的对象 这里的proxyUser就是被代理后的对象 let result; try {//防止出错 result = Reflect.get(target, prop, receiver);//和target[prop]是一样的 反射 执行原始操作 let type = proxies.get_type(result); if (result instanceof Object) { console.log(`${proxies.config.index}, 获取:[${objName}] -> 属性:[${prop.toString()}],type:[${type}]}`); //递归调用 // result = proxies.proxy(result, `${objName}.${prop.toString()}`);//如果prop是Symbol类型${prop}会报错,这里toString是为了防止报错 } else if (typeof result === 'symbol') { console.log(`${proxies.config.index}, 获取:[${objName}] -> 属性:[${prop.toString()}],结果:[${result.toString()}]}`); } else { console.log(`${proxies.config.index}, 获取:[${objName}] -> 属性:[${prop.toString()}],结果:[${result}]}`);// 这里使用${JSON.stringify(result)}输出可能会报错,如果result存在循环引用的话。 } //throw new Error('测试error'); } catch (e) { console.log(`${proxies.config.index}, 获取:[${objName}] -> 属性:[${prop.toString()}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, set: function (target, prop, value, receiver) { let result; try { result = Reflect.set(target, prop, value, receiver); let type = proxies.get_type(value); if (value instanceof Object) { console.log(`设置:[${objName}] -> 属性:[${prop.toString()}],type:[${type}]}`); } else if (typeof value === 'symbol') { console.log(`设置:[${objName}] -> 属性:[${prop.toString()}],value:[${value.toString()}]}`); } else { console.log(`设置:[${objName}] -> 属性:[${prop.toString()}],value:[${value}]}`); } } catch (e) { console.log(`设置:[${objName}] -> 属性:[${prop.toString()}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, getOwnPropertyDescriptor: function (target, prop) { let result;//结果两种 undefined和描述符对象 try { result = Reflect.getOwnPropertyDescriptor(target, prop); let type = proxies.get_type(result); console.log(`getOwnPropertyDescriptor|obj:[${objName}] -> 属性:[${prop.toString()}],type:[${type}]}`); //这里有需要再拦截,拦截的话会输出大量日志信息 //if(typeof result !== 'undefined'){ // result = ldvm.toolsFunc.proxy(result,`${objName}.${prop.toString()}.PropertyDescriptor`); //} } catch (e) { console.log(`getOwnPropertyDescriptor|obj:[${objName}] -> 属性:[${prop.toString()}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, defineProperty: function (target, prop, descriptor) { let result; try { result = Reflect.defineProperty(target, prop, descriptor); console.log(`defineProperty|obj:[${objName}] -> 属性:[${prop.toString()}]}`); } catch (e) { console.log(`defineProperty|obj:[${objName}] -> 属性:[${prop.toString()}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, apply: function (target, thisArg, argumentsList) { //target:函数对象 //thisArg:调用函数的this指针 //argumentsList:数组,函数的入参组长的一个列表 let result; try { result = Reflect.apply(target, thisArg, argumentsList); let type = proxies.get_type(result); if (result instanceof Object) { console.log(`apply|function:[${objName}],type:[${result}]}`); //一般不对函数返回的对象进行拦截,主要还是关注get函数拦截,针对浏览器接口,document,window这些 //特殊情况,可以对函数返回对象进行拦截 } else if (typeof result === 'symbol') { console.log(`apply|function:[${objName}],result:[${result.toString()}]}`); } else { console.log(`apply|function:[${objName}],result:[${result}]}`); } } catch (e) { console.log(`apply|function:[${objName}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, construct: function (target, argArray, newTarget) { //target:函数对象 //argArray:调用函数的this指针 //newTarget:代理对象 let result; try { result = Reflect.construct(target, argArray, newTarget); let type = proxies.get_type(result); console.log(`construct|function:[${objName}],type:[${type}]}`); } catch (e) { console.log(`construct|function:[${objName}],error:[${e.message}]}`); } proxies.config.index += 1; return result; }, deleteProperty: function (target, propKey) { let result = Reflect.deleteProperty(target, propKey); console.log(`deleteProperty|obj:[${objName}] -> 属性:[${propKey.toString()}],result:[${result}]}`); proxies.config.index += 1; return result; }, has: function (target, propKey) {//in 操作符 let result = Reflect.has(target, propKey); console.log(`has|obj:[${objName}] -> 属性:[${propKey.toString()}],result:[${result}]}`); proxies.config.index += 1; return result; }, ownKeys: function (target) {// let result = Reflect.ownKeys(target); console.log(`ownKeys|obj:[${objName}]}`); proxies.config.index += 1; return result; }, getPrototypeOf: function (target) {// let result = Reflect.getPrototypeOf(target); console.log(`getPrototypeOf|obj:[${objName}]}`); proxies.config.index += 1; return result; }, setPrototypeOf: function (target, proto) {// let result = Reflect.setPrototypeOf(target, proto); console.log(`setPrototypeOf|obj:[${objName}]}`); proxies.config.index += 1; return result; }, preventExtensions: function (target) {// let result = Reflect.preventExtensions(target); console.log(`preventExtensions|obj:[${objName}]}`); proxies.config.index += 1; return result; }, isExtensible: function (target, proto) {// let result = Reflect.isExtensible(target); console.log(`isExtensible|obj:[${objName}]}`); proxies.config.index += 1; return result; } }; let config_keys = Object.keys(handler); for (let i = 0; i < config_keys.length; i++) { if (proxies.config[config_keys[i]] !== true) { // console.log('不拦截:' + config_keys[i]) delete handler[config_keys[i]] } else { // console.log('开始拦截:' + config_keys[i]) } } return new Proxy(obj, handler); } module.exports.proxies = proxies;