Javascript 如何重载sessionStorage的点括号[]和setItem()设置程序?
我希望在将项目写入会话存储时记录堆栈跟踪Javascript 如何重载sessionStorage的点括号[]和setItem()设置程序?,javascript,Javascript,我希望在将项目写入会话存储时记录堆栈跟踪 const sessionStorageProxy = new Proxy(sessionStorage, { get(target, name, receiver) { console.log('get', name) console.log(receiver, target) console.trace() return Reflect.get(target, name, receiver); }, set
const sessionStorageProxy = new Proxy(sessionStorage, {
get(target, name, receiver) {
console.log('get', name)
console.log(receiver, target)
console.trace()
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
console.log('set', name)
console.trace()
return Reflect.set(target, name, value, receiver);
}
});
Object.defineProperty(window, "sessionStorage", {
value: sessionStorageProxy,
configurable: true,
enumerable: true,
writable: false
});
const ogSessionStorageSetItem = sessionStorage.setItem;
// this below is acting like sessionStorage.super = 'cool'
sessionStorage.setItem = async function(key, value) {
console.log('Wrote', key);
console.trace();
ogSessionStorageSetItem.apply(this, arguments);
};
这对于会话存储很好。setItem'hello'、'world':
但是在执行sessionStorage时它不起作用。hello='world'或sessionStorage['hello']='world'
我尝试使用代理:
const handler = {
get: function(target, name) {
console.log('get', name)
console.trace()
return target[name];
},
set: function(target, name, value) {
console.log('set', name)
console.trace()
target[name] = value;
},
};
const proxy = new Proxy(sessionStorage, handler);
Object.defineProperty(window, "sessionStorage", {
value: proxy,
configurable: true,
enumerable: true,
writable: false
});
它适用于点和[],但不适用于setItem
如何让他们都工作
更新2:
尝试过的解决方案@Polywhill先生,现在我得到了一个副作用:sessionStorage.setItem=function。。。认为必须将key/value:setItem=>函数定义保存到会话存储中
const sessionStorageProxy = new Proxy(sessionStorage, {
get(target, name, receiver) {
console.log('get', name)
console.log(receiver, target)
console.trace()
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
console.log('set', name)
console.trace()
return Reflect.set(target, name, value, receiver);
}
});
Object.defineProperty(window, "sessionStorage", {
value: sessionStorageProxy,
configurable: true,
enumerable: true,
writable: false
});
const ogSessionStorageSetItem = sessionStorage.setItem;
// this below is acting like sessionStorage.super = 'cool'
sessionStorage.setItem = async function(key, value) {
console.log('Wrote', key);
console.trace();
ogSessionStorageSetItem.apply(this, arguments);
};
您可以将会话存储包装在代理中。这允许您挂接到setter
const sessionStorageProxy=new Proxywindow.sessionStorage{
gettarget、name、Receiver{
返回Reflect.gettarget、name、receiver;
},
设置目标、名称、值、接收者{
console.log'writed',name;
返回Reflect.settarget、名称、值、接收者;
}
};
sessionStorage.setItem=异步函数键,值{
console.log'writed',键;
console.trace;
sessionStorageProxy.applythis,参数;
};
sessionStorage.setItem'hello','world';
console.logsessionStorage.getItem'hello';//世界
sessionStorageProxy.hello='world2';
console.logsessionStorageProxy.hello;//世界2
您可以将会话存储包装在代理中。这允许您挂接到setter
const sessionStorageProxy=new Proxywindow.sessionStorage{
gettarget、name、Receiver{
返回Reflect.gettarget、name、receiver;
},
设置目标、名称、值、接收者{
console.log'writed',name;
返回Reflect.settarget、名称、值、接收者;
}
};
sessionStorage.setItem=异步函数键,值{
console.log'writed',键;
console.trace;
sessionStorageProxy.applythis,参数;
};
sessionStorage.setItem'hello','world';
console.logsessionStorage.getItem'hello';//世界
sessionStorageProxy.hello='world2';
console.logsessionStorageProxy.hello;//世界2
正如@Mr polywhill所提到的,您可以使用代理来包装您的目标对象。对于简单对象,它工作得很好,但一旦你开始使用复杂对象,它很快就会变得混乱 无论如何,根据您更新的问题,在get处理程序中,您将以值的形式返回所有内容,但对于可调用函数的值,您需要发送另一个代理,并在代理中配置apply方法,或者在原始对象上调用函数,而不是代理:
get(target, name, receiver) {
const value = Reflect.get(target, name, receiver);
return typeof value === 'function' ?
value.bind(target) :
value;
}
让我们看看应用了更改的代码:
//在配置代理服务器之前,我们将覆盖它
//之后设置setItem会将此方法放在代理本身上,而不是sessionStorage对象上
//覆盖会话存储
const ogSessionStorageSetItem=sessionStorage.setItem;
sessionStorage.setItem=异步函数键,值{
console.log'writed',键;
console.trace;
ogSessionStorageSetItem.applythis,参数;
};
//创建代理
const sessionStorageProxy=新的ProxysessionStorage{
获取目标、名称、接收者{
const value=Reflect.gettarget、name、receiver;
返回值的类型==='函数'?
value.bindtarget:
价值
},
设置目标、名称、值、接收者{
如果名称=='setItem'{
返回false;
}
返回Reflect.settarget、名称、值、接收者;
}
};
Object.DefineProperty窗口、会话存储、{
值:sessionStorageProxy,
对,,
可枚举:正确,
可写:false
};
sessionStorage.key1=值1;
会话存储[key2]=值2;
sessionStorage.setItem'key3','value3';
console.logsessionStorage.key1;
console.logsessionStorage[key2];
console.logsessionStorage.getItemkey3 正如@Mr polywhill所提到的,您可以使用代理来包装您的目标对象。对于简单对象,它工作得很好,但一旦你开始使用复杂对象,它很快就会变得混乱 无论如何,根据您更新的问题,在get处理程序中,您将以值的形式返回所有内容,但对于可调用函数的值,您需要发送另一个代理,并在代理中配置apply方法,或者在原始对象上调用函数,而不是代理:
get(target, name, receiver) {
const value = Reflect.get(target, name, receiver);
return typeof value === 'function' ?
value.bind(target) :
value;
}
让我们看看应用了更改的代码:
//在配置代理服务器之前,我们将覆盖它
//之后设置setItem会将此方法放在代理本身上,而不是sessionStorage对象上
//覆盖会话存储
const ogSessionStorageSetItem=sessionStorage.setItem;
sessionStorage.setItem=异步函数键,值{
console.log'writed',键;
console.trace;
ogSessionStorageSetItem.applythis,参数;
};
//创建代理
const sessionStorageProxy=新的ProxysessionStorage{
获取目标、名称、接收者{
const value=Reflect.gettarget、name、receiver;
返回值的类型==='函数'?
value.bindtarget:
价值
},
设置目标、名称、值、接收者{
如果名称=='setItem'{
返回false;
}
返回R
eflect.settarget,名称,值,接收者;
}
};
Object.DefineProperty窗口、会话存储、{
值:sessionStorageProxy,
对,,
可枚举:正确,
可写:false
};
sessionStorage.key1=值1;
会话存储[key2]=值2;
sessionStorage.setItem'key3','value3';
console.logsessionStorage.key1;
console.logsessionStorage[key2];
console.logsessionStorage.getItemkey3;点和括号语法做同样的事情。显然,直接调用底层属性会绕过setter函数。使用代理更新我的代码点括号语法也会做同样的事情。显然,直接调用底层属性会绕过setter函数。使用proxyThank更新了我的代码。我得到了sessionStorage Proxy。apply不是一个函数,我如何修复它?@MichelDelpech我想你可以将它改为sessionStorage.apply。我有一些奇怪的副作用。现在,sessionStorage.setItem认为它必须注册一个新的键/值对:setItem=>function definition哈哈更新了我的答案谢谢,我得到了sessionStorage Proxy.apply不是一个函数,我该如何修复它?@MichelDelpech我想你可以将它改为sessionStorage.apply。我有一些奇怪的副作用。现在,sessionStorage.setItem认为它必须注册一个新的键/值对:setItem=>function definition haha更新了我的答案