location
のようなオブジェクトの一部は読み取り専用です。抽象的なオブジェクトを作成したり、テスト容易性のためにDIを使用すると便利です。
sessionStorage
をそのまま用いるものとする。通常、それ以上の抽象化は必要ありません。その機能を拡張または変更する必要がある場合は、カスタムクラスを作成できます。それはStorageインターフェイスを実装するか、独自のインターフェイスを持つことができます。
Proxy
の使用はここでは正当ではありません。それは遅く、コードがES5環境で使用されることを制限します。
カスタムクラスまたはオブジェクトは、元のsessionStorage
メソッドをラップするだけです。ストレージAPIは小さいので、コードの〜20行でラッパークラスの結果:
class CustomSessionStorage {
get length() {
return sessionStorage.length;
}
getItem(key) {
return sessionStorage.getItem(key);
}
...
}
sessionStorage
は、オブジェクトがエキゾチックです。 Storage
から継承していますが、Storage
はコンストラクタではなく、sessionStorage
メソッドはsessionStorage
に直接バインドする必要があります。したがって、CustomSessionStorage.prototype = sessionStorage
と一緒に動作させることはできません。さらに、sessionStorage
は、バインドされるべきであるlength
のプロパティ記述子を持っています。
それを拡張するために、より一般的な方法は、元のメソッドをラップの基本クラスを提供することで、さらに拡張することができます。
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.parse'を設定するたびにデータを' JSON.stringify 'したいのであれば、毎回これをやっていない時間の90%を取得します。私は単に私のproxylayerがこの世話をしたい。 –
私はここにプロキシの本当の必要性を見ません。これは、通常のクラス(またはストレージはシングルトンであるはずなのでオブジェクト)によって処理できます。元の質問については、どうしたら?*を使って再びそのスコープにアクセスするには、 'setItem'の中で' sessionStorage.setItem() 'と明示的に参照する必要があります。 'set(k、v){this.setItem(a、msg)}'。プロキシメソッドで 'this'を使うことができます。 – estus
元の 'sessionStorage'オブジェクトのように振る舞うようにするには、オリジナルを単にラップするだけですべてのメソッドを実装する必要があります。 –