可以代理对象,监控对象,方便调试代码和补环境,提供学习使用。
//Proxy代理器
ldvm.toolsFunc.proxy = function proxy(obj,objName){
//obj:原始对象
//objName:原始对象的名字
if(!ldvm.config.proxy){
console.log('未开通代理');
return obj;
}
let handler = {
get:function(target,prop,receiver){//三个参数
//target: 原始对象 这里是user
//prop:属性 只有string和symbol两个类型
//receiver:代理后的对象 这里的proxyUser就是被代理后的对象
let result;
try{//防止出错
result = Reflect.get(target,prop,receiver);//和target[prop]是一样的 反射 执行原始操作
let type = ldvm.toolsFunc.getType(result);
if(result instanceof Object){
console.log(`{get|obj:[${objName}] -> prop:[${prop.toString()}],type:[${type}]}`);
//递归调用
result = ldvm.toolsFunc.proxy(result,`${objName}.${prop.toString()}`);//如果prop是Symbol类型${prop}会报错,这里toString是为了防止报错
}else if(typeof result === 'symbol'){
console.log(`{get|obj:[${objName}] -> prop:[${prop.toString()}],ret:[${result.toString()}]}`);
}else{
console.log(`{get|obj:[${objName}] -> prop:[${prop.toString()}],ret:[${result}]}`);// 这里使用${JSON.stringify(result)}输出可能会报错,如果result存在循环引用的话。
}
//throw new Error('测试error');
}catch(e){
console.log(`{get|obj:[${objName}] -> prop:[${prop.toString()}],error:[${e.message}]}`);
}
return result;
},
set:function(target,prop,value,receiver){
let result;
try{
result = Reflect.set(target,prop,value,receiver);
let type = ldvm.toolsFunc.getType(value);
if(value instanceof Object){
console.log(`{set|obj:[${objName}] -> prop:[${prop.toString()}],type:[${type}]}`);
}else if(typeof value === 'symbol'){
console.log(`{set|obj:[${objName}] -> prop:[${prop.toString()}],value:[${value.toString()}]}`);
}else{
console.log(`{set|obj:[${objName}] -> prop:[${prop.toString()}],value:[${value}]}`);
}
}catch(e){
console.log(`{set|obj:[${objName}] -> prop:[${prop.toString()}],error:[${e.message}]}`);
}
return result;
},
getOwnPropertyDescriptor:function(target,prop){
let result;//结果两种 undefined和描述符对象
try{
result = Reflect.getOwnPropertyDescriptor(target,prop);
let type = ldvm.toolsFunc.getType(result);
console.log(`{getOwnPropertyDescriptor|obj:[${objName}] -> prop:[${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:[${prop.toString()}],error:[${e.message}]}`);
}
return result;
},
defineProperty:function(target,prop,descriptor){
let result;
try{
result = Reflect.defineProperty(target,prop,descriptor);
console.log(`{defineProperty|obj:[${objName}] -> prop:[${prop.toString()}]}`);
}catch(e){
console.log(`{defineProperty|obj:[${objName}] -> prop:[${prop.toString()}],error:[${e.message}]}`);
}
return result;
},
apply:function(target,thisArg,argumentsList){
//target:函数对象
//thisArg:调用函数的this指针
//argumentsList:数组,函数的入参组长的一个列表
let result;
try{
result = Reflect.apply(target,thisArg,argumentsList);
let type = ldvm.toolsFunc.getType(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}]}`);
}
return result;
},
construct:function(target,argArray,newTarget){
//target:函数对象
//argArray:调用函数的this指针
//newTarget:代理对象
let result;
try{
result = Reflect.construct(target,argArray,newTarget);
let type = ldvm.toolsFunc.getType(result);
console.log(`{construct|function:[${objName}],type:[${type}]}`);
}catch(e){
console.log(`{construct|function:[${objName}],error:[${e.message}]}`);
}
return result;
},
deleteProperty:function(target,propKey){
let result = Reflect.deleteProperty(target,propKey);
console.log(`{deleteProperty|obj:[${objName}] -> prop:[${propKey.toString()}],result:[${result}]}`);
return result;
},
has:function(target,propKey){//in 操作符
let result = Reflect.has(target,propKey);
console.log(`{has|obj:[${objName}] -> prop:[${propKey.toString()}],result:[${result}]}`);
return result;
},
ownKeys:function(target){//
let result = Reflect.ownKeys(target);
console.log(`{ownKeys|obj:[${objName}]}`);
return result;
},
getPrototypeOf:function(target){//
let result = Reflect.getPrototypeOf(target);
console.log(`{getPrototypeOf|obj:[${objName}]}`);
return result;
},
setPrototypeOf:function(target,proto){//
let result = Reflect.setPrototypeOf(target,proto);
console.log(`{setPrototypeOf|obj:[${objName}]}`);
return result;
},
preventExtensions:function(target){//
let result = Reflect.preventExtensions(target);
console.log(`{preventExtensions|obj:[${objName}]}`);
return result;
},
isExtensible:function(target,proto){//
let result = Reflect.isExtensible(target);
console.log(`{isExtensible|obj:[${objName}]}`);
return result;
}
};
return new Proxy(obj,handler);
}