0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

localStorage を Proxy で拡張して文字列以外を保存できるようにする

0
Last updated at Posted at 2025-07-04

やりたいこと

localStorage は便利だけど、保存した値が文字列に変換されてしまうので使いにくさを感じるときがある。1

localStorage.setItem('hoge', true);
localStorage.getItem('hoge');
// 'true'

localStorage.setItem('hoge', 123);
localStorage.getItem('hoge');
// '123'

localStorage.setItem('hoge', [1, 2, 3]);
localStorage.getItem('hoge');
// '1,2,3'

localStorage.setItem('hoge', { fuga: 123 });
localStorage.getItem('hoge');
// '[object Object]'

localStorage.clear();

localStorage.getItem('hoge');
// null

Boolean や整数、その他オブジェクトをできるだけそのままの値で保存したい。

方法

  • localStorage に setItem() で値を保存する際、JSON 文字列に変換して保存する
  • localStorage から getItem() で値を取り出す際、取り出した JSON 文字列をパースする
  • ProxyReflect を使って、localStorage の機能を拡張した jsonLocalStorage オブジェクトを作成する2
    • そうすることで setItem(), getItem() 以外のインターフェイス (removeItem()clear() など) をそのまま利用できるようにする
const jsonLocalStorage = new Proxy(localStorage, {
  get(target, prop, _receiver) {
    if (prop === 'getItem') {
      return (keyName) => {
        const getItem = Reflect.get(target, prop).bind(target);
        const keyValue = getItem(keyName);
        
        return JSON.parse(keyValue);
      };
    }
    if (prop === 'setItem') {
      return (keyName, keyValue) => {
        const setItem = Reflect.get(target, prop).bind(target);
        setItem(keyName, JSON.stringify(keyValue));
      };
    }

    return Reflect.get(target, prop).bind(target);
  }
});
jsonLocalStorage.setItem('hoge', true);
jsonLocalStorage.getItem('hoge');
// true

jsonLocalStorage.setItem('hoge', 123);
jsonLocalStorage.getItem('hoge');
// 123

jsonLocalStorage.setItem('hoge', [1, 2, 3]);
jsonLocalStorage.getItem('hoge');
// [1, 2, 3]

jsonLocalStorage.setItem('hoge', { fuga: 123 });
jsonLocalStorage.getItem('hoge');
// {fuga: 123}

jsonLocalStorage.clear();

jsonLocalStorage.getItem('hoge');
// null

参考

  1. そのせいで false を保存したつもりが 'false' になっていてバグったことが 😢

  2. Ruby の SimpleDelegator と同じことがやりたくて ChatGPT に質問したら、Proxy を存在を知りました 🙌

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?