sessionStorage 代理 class 范围

sessionStorage proxy class scope

我想知道如何从我的自定义方法中访问本机 sessionStorage 范围。

我的例子:

https://jsfiddle.net/3mc7ao7j/1/

在第 3 行,我希望能够在对数据执行突变后代理到我的本地 sessionStorage

我如何再次访问该范围?我知道我可以打电话:

sessionStorage.setItem()

但这很有效,因为它是全球可用的,这样做感觉不对。主要是因为我还想知道如何在没有全局可用对象的情况下执行此操作,以便我可以学习如何代理其他对象。

一些 window 对象,如 location 是只读的,在它们之上创建抽象或使用 DI 进行测试可能很有用。

sessionStorage 应该按原样使用。通常不需要对其进行抽象。如果要扩展或修改其功能,可以创建自定义 class。它可以实现 Storage 接口或拥有自己的接口。

这里使用 Proxy 是不合理的。它很慢并且限制了代码在 ES5 环境中的使用。

自定义 class 或对象可以只包装原始 sessionStorage 方法。由于 Storage API 很小,wrapper class 导致大约 20 行代码:

class CustomSessionStorage {
  get length() {
    return sessionStorage.length;
  }

  getItem(key) {
    return sessionStorage.getItem(key);
  }
  ...
}

sessionStorage 对象很奇特。虽然它继承自 Storage,但 Storage 不是构造函数,sessionStorage 方法应该直接绑定到 sessionStorage,所以不可能只使用 CustomSessionStorage.prototype = sessionStorage。此外,sessionStorage 还应绑定 length 属性 描述符。

一种更通用的扩展方法是提供一个基础 class 来包装原始方法并可以进一步扩展:

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
}