5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

関数型プログラミング(??)でストレージ操作

Last updated at Posted at 2014-12-18

2015/02/16 追記
続きみたいなのを書きました。

**「関数型プログラミングってカッコイイ!!!」**と思ったので、勉強し始めました。
ちょっと勉強してみたところで何か書いてみたくなったので、ストレージ管理のModelを書いてみました。

※ 本Modelを使用する際はオブジェクト指向的に、内部処理のみ関数型プログラミングのつもりで書いています。

が、しかし

「これ、関数型プログラミングとは言えないんじゃないか??」という指摘を多々頂いたので、Qiitaに公開してどこがどうダメなのかを教えていただけたらな、と思いました。

ライブラリにはLo-Dash v2.4.1を使用しています。

皆様、宜しくお願い致します。

storage.js
/**
 * ストレージ管理
 */

module.exports = (function(){
  /**
   *
   * @param type local|session|cookie
   * @constructor
   */
  function StorageModel(type){
    this.myStorages = [
      {
        'type':      'local',
        'available': isSupport(localStorage),
        'set':       setLocalStorageItem,
        'get':       getLocalStorageItem,
        'remove':    removeLocalStorageItem
      },
      {
        'type':      'session',
        'available': isSupport(sessionStorage),
        'set':       setSessionStorageItem,
        'get':       getSessionStorageItem,
        'remove':    removeSessionStorageItem
      },
      {
        'type':      'cookie',
        'available': isSupport(document.cookie),
        'set':       setCookie,
        'get':       getCookie,
        'remove':    removeCookie
      }
    ];

    // 使用するストレージ
    this.myStorage = decideStorage(findStorageFromMap(type, this.myStorages), this.myStorages);
  }

  /**
   * ストレージへの保存
   *
   * @param {String} key
   * @param {String} value
   * @param {int} expireDays
   */
  StorageModel.prototype.setItem = function(key, value, expireDays){
    this.myStorage.set.apply(this, [key, value, expireDays]);
  };

  /**
   * ストレージからの取得
   *
   * @param {String} key
   * @return {mixed}
   */
  StorageModel.prototype.getItem = function(key){
    return this.myStorage.get.apply(this, [key]);
  };

  /**
   * ストレージからの削除
   *
   * @param {String} key
   */
  StorageModel.prototype.removeItem = function(key){
    this.myStorage.remove.apply(this, [key]);
  };

  /**
   * 指定されたストレージ機能をサポートしているか否か
   *
   * @param {Object} storage localStorage|sessionStorage|document.cookie
   * @returns {boolean}
   */
  function isSupport(storage){
    return (_.isUndefined(storage)) ? false : true;
  }

  /**
   * ストレージの取得
   *
   * @param {String} type local|session|cookie
   * @param {Array} storages
   * @returns ストレージ
   */
  function findStorageFromMap(type, storages){
    return _.find(storages, function(st){
      return st.type == type;
    });
  }

  /**
   * 使用ストレージタイプの決定
   * ただし、localStorage|sessionStorageが存在しない場合はcookieになる
   *
   * @param {Object} localStorage|sessionStorage|document.cookie
   * @returns {Object} local|session|cookie
   */
  function decideStorage(storage, storages){
    return (_.isUndefined(storage) === false && storage.available === true) ? storage : _.find(storages, function(st){ return st.type == 'cookie'; });
  }

  /**
   * localStorageへの保存
   *
   * @param {String} key
   * @param {String} value
   * @return localStorage
   */
  function setLocalStorageItem(key, value, expireDays){
    localStorage.setItem(key, JSON.stringify(value));

    return localStorage;
  }

  /**
   * sessionStorageへの保存
   *
   * @param {String} key
   * @param {String} value
   * @return sessionStorage
   */
  function setSessionStorageItem(key, value, expireDays){
    sessionStorage.setItem(key, JSON.stringify(value));

    return sessionStorage;
  }

  /**
   * Cookieへの保存
   *
   * @param {String} key
   * @param {String} value
   * @param {int} expireDays
   * @return document.cookie
   */
  function setCookie(key, value, expireDays){
    document.cookie = generateCookieData(key, value, expireDays, generateCookieExpireDateString);

    return document.cookie;
  }

  /**
   * Cookie保存用文字列の生成
   *
   * @param {String} key
   * @param {String} value
   * @param {int} expire
   * @param {function} generator
   */
  function generateCookieData(key, value, expire, generator){
    return encodeURIComponent(key) + '=' + encodeURIComponent(value) + generator.call(null, expire);
  }

  /**
   * Cookieの保存期間文字列生成
   *
   * @param {int} expireDays
   * @param {String} utc
   */
  function generateCookieExpireDateString(expireDays){
    if (_.isUndefined(expireDays)) {
      return '';
    }

    var current = new Date();
    var date = new Date(current.getTime() + (60 * 60 * 24 * 1000 * expireDays));

    return '; expires=' + date.toUTCString();
  }

  /**
   * Cookie削除の為の保存期間文字列生成
   *
   * @param {String} utc
   */
  function generateCookieRemoveDateString(){
    return '; expires=Thu, 01 Jan 1970 00:00:00 GMT';
  }

  /**
   * localStorageから取得
   *
   * @param {String} key
   * @return {mixed}
   */
  function getLocalStorageItem(key){
    return JSON.parse(localStorage.getItem(key));
  }

  /**
   * sessionStorageから取得
   *
   * @param {String} key
   * @return {mixed}
   */
  function getSessionStorageItem(key){
    return JSON.parse(sessionStorage.getItem(key));
  }

  /**
   * Cookieから取得
   *
   * @param {String} key
   * @return {mixed}
   */
  function getCookie(key){
    // Cookie情報を;で区切って配列化
    // その後、=で区切って、{key: value}の形に生成
    // 返ってきた値から、keyを使用して値を取得する
    return (function(list){
      return (hasCookie(key, list)) ? decodeURIComponent(list[key]) : null;
    })(convertCookieToArray());
  }

  /**
   * Cookie情報の配列化
   *
   * @return {Array}
   */
  function convertCookieToArray(){
    return _.reduce(_.toArray(document.cookie.split(';')), function(result, cookie){
      var data = cookie.split('=');
      var cookieKey   = data[0],
          cookieValue = data[1];

      result[cookieKey.trim()] = cookieValue;

      return result;
    }, {});
  }

  /**
   * 指定されたCookieが存在するか否か
   *
   * @param {String} key
   * @param {Array} cookies
   * @return {boolean} 存在する場合:true|存在しない場合:false
   */
  function hasCookie(key, cookies){
    return _.has(cookies, key);
  }

  /**
   * localStorageから削除
   *
   * @param {String} key
   */
  function removeLocalStorageItem(key){
    localStorage.removeItem(key);

    return localStorage;
  }

  /**
   * sessionStorageから削除
   *
   * @param {String} key
   */
  function removeSessionStorageItem(key){
    sessionStorage.removeItem(key);

    return sessionStorage;
  }

  /**
   * Cookieから削除
   *
   * @param {String} key
   */
  function removeCookie(key){
    if (hasCookie(key, convertCookieToArray())) {
      document.cookie = generateCookieData(key, '', undefined, generateCookieRemoveDateString);
    }

    return document.cookie;
  }

  return StorageModel;
})();
app.js
var storage = require('./storage');

var StLocal   = new storage('local'),
    StSession = new storage('session'),
    StCookie  = new storage('cookie');

StLocal.setItem('foo', '1234abcd');
StSession.setItem('foo', 'hijk5678');
StCookie.setItem('foo', '90opqrstu');

console.log(StLocal.getItem('foo');   // 1234abcd
console.log(StSession.getItem('foo'); // hijk5678
console.log(StCookie.getItem('foo');  // 90opqrstu
5
5
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
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?