Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何重载sessionStorage的点括号[]和setItem()设置程序?_Javascript - Fatal编程技术网

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更新了我的答案