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