您好我想知道如何为sessionStorage
。
我可以通过对sessionStorage
的方法调用来实现我自己的类和代理。例如,使用一些快速伪代码:
class customStorage {
set(key, value) {
sessionStorage.setItem(key, value);
}
}
我会像这样使用它:
const customStorage = new customStorage();
customStorage.set('my-key', 'hello there');
一切都很好,但是我希望用户可以自由地在我的代理上使用其他本地sessionStorage
方法,而这些方法可能不会在我的代理中实现。
对于类似sessionStorage
的内容,即使他们所做的一切都代理到sessionStorage
而没有任何干预,也可以自己编写它们。
对于更大的地方,我只会操纵20种中的5种方法或其他东西,这似乎不可行。
用原型覆盖原生功能似乎也是导致许多wtfs-per-minute
的死亡陷阱。
到目前为止,我从Javascript中的'代理模式'中读到了它们都实现了原始Object中的所有方法。我被迫这样做了吗?
是否有某种方法可以在构造函数中创建ES6类并将该类的原型设置为sessionStorage?
答案 0 :(得分:2)
我希望用户可以自由地在我的代理上使用其他本地
sessionStorage
方法,而这些方法可能无法在我的代理中实现。
如果他打算这样做,我宁愿让用户直接使用本地sessionStorage
。您的实现确实有自己独立的功能,它在内部使用sessionStorage
但不是sessionStorage
。没有理由在您的对象上实现其接口。 (另见composition over inheritance)。
是否有某种方法可以创建ES6
class
并在构造函数中将该类的原型设置为sessionStorage
?
没有。即使您想要实现该接口,您的对象也不是真正的SessionStorage
实例。同样在这种特殊情况下,sessionStorage
是一个单例,你不能实例化第二个SessionStorage
,所以继承在这里绝对不起作用。
有三种方法可以解决这个问题(我将为通用案例编写代码,并从要包装的任意对象进行实例化,您可能需要一个类似于静态单例的自定义存储):
Mixins来装饰物体。不要创建另一个实例,只需覆盖原始属性。 (对于内置对象,这可能是不可能的)
function custom(orig) {
orig.get = function() { … };
return orig;
}
寄生继承,使用对象的反射创建完整的包装。
function custom(orig) {
const obj = {
get() { … };
};
for (const p in orig) { // assuming everything is enumerable - alternatively use
// for (const p of Object.getOwnPropertyNames(…))
// or even incorporating the prototype chain
obj[p] = typeof orig[p] == "function"
? (...args) => orig[p](...args)
: orig[p];
}
return obj;
}
带有suitable handler的文字Proxy
:
const customMethods = {
get() { … }
};
const handler = {
has(target, name) {
return name in customMethods || name in target;
},
get(target, name) {
if (name in customMethods) return customMethods[name];
else return target[name];
// if its a native object with methods that rely on `this`, you'll need to
// return target[name].bind(target)
// for function properties
}
}
function custom(orig) {
return new Proxy(orig, handler);
}