如何为 sessionStorage 编写合适的 ES6 包装器
How to write a proper ES6 wrapper for something like sessionStorage
你好,我想知道如何为 sessionStorage
.
之类的东西编写合适的包装器
我可以通过调用 sessionStorage
的方法实现自己的 class 和代理。例如一些快速伪代码:
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
.
的死亡陷阱
到目前为止,我从 'proxy patterns' 在 Javascript 中读到的内容都实现了原始对象的所有方法。我是被迫这样做的吗?
是否有某种方法可以创建 ES6 class 并将其原型 class 设置为构造函数中的 sessionStorage 之类的?
I would like for a user to have the freedom to use other native sessionStorage
methods on my proxy that I might not implement myself in my proxy.
我宁愿让用户自由地直接 sessionStorage
使用本机 如果他打算这样做。您的实现确实有自己的独立功能,它在内部使用 sessionStorage
但不是 sessionStorage
。没有理由在您的对象上实现它的接口。 (另请参阅 composition over inheritance)。
Is there some sort of way to create an ES6 class
and set the prototype of that very class to sessionStorage
in the constructor or something?
没有。即使您想要实现该接口,您的对象也不是真正的 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);
}
你好,我想知道如何为 sessionStorage
.
我可以通过调用 sessionStorage
的方法实现自己的 class 和代理。例如一些快速伪代码:
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
.
到目前为止,我从 'proxy patterns' 在 Javascript 中读到的内容都实现了原始对象的所有方法。我是被迫这样做的吗?
是否有某种方法可以创建 ES6 class 并将其原型 class 设置为构造函数中的 sessionStorage 之类的?
I would like for a user to have the freedom to use other native
sessionStorage
methods on my proxy that I might not implement myself in my proxy.
我宁愿让用户自由地直接 sessionStorage
使用本机 如果他打算这样做。您的实现确实有自己的独立功能,它在内部使用 sessionStorage
但不是 sessionStorage
。没有理由在您的对象上实现它的接口。 (另请参阅 composition over inheritance)。
Is there some sort of way to create an ES6
class
and set the prototype of that very class tosessionStorage
in the constructor or something?
没有。即使您想要实现该接口,您的对象也不是真正的 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); }