Some window
objects like location
are read-only, it can be useful to create abstractions over them or make use of DI for testability.
sessionStorage
is supposed to be used as is. Usually no abstractions over it are needed. If its functionality should be extended or modified, a custom class can be created. It can implement Storage interface or have its own.
The use of Proxy
is unjustified here. It is slow and restricts the code from being used in ES5 environments.
Custom class or object can just wrap original sessionStorage
methods. Since Storage API is small, wrapper class results in ~20 lines of code:
class CustomSessionStorage {
get length() {
return sessionStorage.length;
}
getItem(key) {
return sessionStorage.getItem(key);
}
...
}
sessionStorage
object is exotic. Although it inherits from Storage
, Storage
is not a constructor, and sessionStorage
methods should be bound to sessionStorage
directly, so it's not possible to make it work just with CustomSessionStorage.prototype = sessionStorage
. Additionally, sessionStorage
has length
property descriptor that should be bound as well.
A more general way to extend it is to provide a base class that wraps original methods and can be extended further:
function BaseSessionStorage() {}
for (let prop of Object.getOwnPropertyNames(Storage.prototype)) {
if (typeof sessionStorage[prop] === 'function') {
// bind all sessionStorage methods
BaseSessionStorage.prototype[prop] = sessionStorage[prop].bind(sessionStorage);
} else {
// a proxy for other props, length is read-only getter
Object.defineProperty(BaseSessionStorage.prototype, prop, {
get: () => sessionStorage[prop],
set: val => { sessionStorage[prop] = val }
});
}
}
class CustomSessionStorage extends BaseSessionStorage {
getItem(key) {
return super.getItem(key);
}
// the rest of API is inherited
}
JSON.stringify
data whenever I set something andJSON.parse
it get I get an item 90% of the time I am not going to do this everytime. I simply want my proxylayer to take care of this. – Mcpherson