复制localStorage原型至其他对象时出现“Uncaught TypeError: Illegal invocation”错误的解决方法
修复localStorage副本调用setItem时的"Illegal invocation"错误
我之前也踩过这个坑!你遇到的问题本质是localStorage的内置方法严重依赖自身的上下文(也就是this指向)——当你通过原型继承把Storage的方法挂到自己的obj上后,调用obj.setItem时,方法内部的this指向的是你的obj,而不是原生的localStorage实例。浏览器的内置Storage方法会严格检查this的身份,不允许在非原生实例的上下文里运行,所以就抛出了"Illegal invocation"错误。
下面给你两种实用的修复方案:
方案一:手动绑定方法的上下文到localStorage
遍历localStorage的所有属性和方法,把方法绑定到原localStorage的this上,这样调用时内部上下文就对了:
var obj = {}; // 遍历localStorage的所有自有属性(包括方法) for (const key of Object.getOwnPropertyNames(localStorage)) { const value = localStorage[key]; if (typeof value === 'function') { // 把方法的this绑定到原生localStorage obj[key] = value.bind(localStorage); } else { // 普通属性直接复制 obj[key] = value; } } // 现在调用完全正常 obj.setItem("a", 1); console.log(localStorage.getItem("a")); // 输出 "1"
方案二:用Proxy创建一个镜像代理
通过Proxy拦截obj的所有属性访问和赋值,自动把操作转发到localStorage,同时给方法绑定正确的上下文:
const obj = new Proxy({}, { // 拦截属性读取 get(target, prop) { const value = localStorage[prop]; if (typeof value === 'function') { // 方法绑定this到localStorage return value.bind(localStorage); } // 普通属性直接返回localStorage的值 return value; }, // 拦截属性赋值 set(target, prop, value) { localStorage[prop] = value; return true; } }); obj.setItem("a", 1); console.log(obj.getItem("a")); // 输出 "1"
为什么你原来的方法不行?Object.setPrototypeOf(obj, Object.getPrototypeOf(localStorage))只是让obj继承了Storage原型上的方法,但这些方法运行时的this是obj,不是原生的Storage实例——浏览器内置的安全机制会阻止这种“非法调用”,所以这条路走不通。
内容的提问来源于stack exchange,提问作者yoyo44
相关产品推荐
相关产品推荐

