总结JavaScript三种数据存储方式之间的区别


Posted in Javascript onMay 03, 2016

sessionStorage 、localStorage 和 cookie 之间的共同点:
都是保存在浏览器端,且同源的。

sessionStorage 、localStorage 和 cookie 之间的区别:
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。
Web Storage 的 api 接口使用更方便。

封装的localStorage的方法,可以控制存储数据的条数,以及时间

define(function (require) {
  var $ = require('jquery');
  var Cache = {};

  function support() {
    var _t = !(typeof window.localStorage === 'undefined');
    return _t;
  }


  $.extend(Cache, {
    config: {
      size: 5,
      // lifeTime: 86400 //一天的秒数
      lifeTime: 1*60
    },
    localStorage: window.localStorage,
    memQueue: (function () {
      if (support()) {
        var jsonStr = window.localStorage.getItem('LRUConfig');
        return jsonStr ? JSON.parse(jsonStr) : {
          keys: {},
          objs: []
        };
      } else {
        return {};
      }
    })(),

    get: function(appid, url) {
      if (true == support()) {
        var key = appid + ':' + url;
        //开始做LRU算法。
        this.LRU(key);
        //LRU算法结束。
        var isFresh = true;
        var nowTime = (new Date()).getTime() / 1000;
        if(key in this.memQueue.keys){
          var cacheTime = this.memQueue.keys[key].life / 1000;
          //如果过期时间超过 配置的lifeTime,
          //则清除掉当前缓存
          if(nowTime - cacheTime >= this.config.lifeTime){
            delete this.memQueue.keys[key];
            for (var i=0, len = this.memQueue.objs.length; i < len; i++) {
              var _o = this.memQueue.objs[i];
              if(_o.key == key){
                this.memQueue.objs.splice(i,1);
                break;
              }
            }
            isFresh = false;
          }
        }
        //如果isFresh为假,就是已过期,则返回null,否则从localStorage中取
        return (false == isFresh) ? null : this.localStorage[key];
      }
    },
    set: function(appid, url, value) {
      if (true == support()) {
        var key = appid + ':' + url;
        var lruKey = this.getLRU();
        //淘汰最近最少使用的这个。
        //另外起一个方法读取最符合淘汰的这个
        //前提是当前这个key,不在localStorage里面。
        if (lruKey) {
          this.localStorage.removeItem(lruKey);
        }
        //开始设置一下这个值
        //为了兼容性,用以下方法设置
        if (typeof this.memQueue.objs != 'undefined' &&
          this.memQueue.objs.length <= this.config.size) {
          this.localStorage.removeItem(key);

        } else {
          while (this.memQueue.objs.length >= this.config.size) {
            var lruKey = this.getLRU();
            //淘汰最近最少使用的这个。
            //另外起一个方法读取最符合淘汰的这个
            if (lruKey) {
              this.localStorage.removeItem(lruKey);
              delete this.memQueue.keys[lruKey];
              for (var i = 0; i < this.memQueue.objs.length; i++) {
                var _o = this.memQueue.objs[i];
                if(_o.key == lruKey){
                  this.memQueue.objs.splice(i,1);
                  break;
                }
              }
            }
          }
        }

        this.localStorage[key] = value;
        //当前的key,也必须lru一下
        this.LRU(key);
        //lru结束

        this.localStorage.setItem('LRUConfig', JSON.stringify(this.memQueue));
      }
    },
    /*
     * 近期最少使用算法
     */
    LRU: function(key) {
      var memQueue = this.memQueue;
      if (typeof memQueue.objs != 'undefined') {
        var _o = memQueue.objs;

        //开始计算那个要淘汰的key,
        //就是那个times最大的,如果times最大的有几个
        //则返回那个time最小的
        var isIn = false;
        for (var i = 0, len = _o.length; i < len; i++) {
          _o[i].times = (key == _o[i].key) ? 0 : _o[i].times + 1;
          _o[i].time = (key == _o[i].key) ? (new Date()).getTime() : _o[i].time;
          if(key == _o[i].key && false == isIn){
            isIn = true;
          }
        }
        // 如果
        if(false == isIn){
          var _to = {
            'key': key,
            'times': 0,
            'time': (new Date()).getTime(),
            'life': (new Date()).getTime()
          };
          this.memQueue.keys[key] = _to;
          this.memQueue.objs.push(_to);
        }
        _o.sort(function(f, s) {
          //按times降序排列。
          if (f.times < s.times) {
            return 1;
          } else if (f.times > s.times) {
            return -1;
          } else {
            //开始比较time
            //按time,时间升序排列
            if (f.time < s.time) {
              return -1;
            } else {
              return 1;
            }
          }
        });
      } else {
        this.memQueue.objs = [];
        this.memQueue.keys = {};
        var _to = {
          'key': key,
          'times': 0,
          'time': (new Date()).getTime(),
          'life': (new Date()).getTime()
        };
        this.memQueue.keys[key] = _to;
        this.memQueue.objs.push(_to);
        return null;
      }
    },
    /*
     * 读取需要淘汰的一项
     */
    getLRU: function() {
      var _o = this.memQueue.objs;
      if (_o) {
        return (_o.length >= this.config.size) ? _o.shift().key : null;
      }

      return null;

    }
  });


  return {
    'cache': Cache
  };
});

使用方法

var cache = require('cache');
// set 值
cache.Cache.set('ip', '你自己的一个url', value);

// get值
cache.Cache.get('ip')
Javascript 相关文章推荐
js 操作css实现代码
Jun 11 Javascript
Array的push与unshift方法性能比较分析
Mar 05 Javascript
js将字符串转成正则表达式的实现方法
Nov 13 Javascript
原生JS和JQuery动态添加、删除表格行的方法
May 28 Javascript
jQuery入门之层次选择器实例简析
Dec 11 Javascript
iscroll.js的上拉下拉刷新时无法回弹的解决方法
Feb 18 Javascript
JavaScript编写页面半透明遮罩效果的简单示例
May 09 Javascript
14 个折磨人的 JavaScript 面试题
Aug 08 Javascript
基于node.js依赖express解析post请求四种数据格式
Feb 13 Javascript
纯原生js实现贪吃蛇游戏
Apr 16 Javascript
JavaScript console的使用方法实例分析
Apr 28 Javascript
纯js+css实现在线时钟
Aug 18 Javascript
深入解析jQuery中Deferred的deferred.promise()方法
May 03 #Javascript
浅析函数声明和函数表达式——函数声明的声明提前
May 03 #Javascript
详解JavaScript异步编程中jQuery的promise对象的作用
May 03 #Javascript
jQuery的promise与deferred对象在异步回调中的作用
May 03 #Javascript
JavaScript的MVVM库Vue.js入门学习笔记
May 03 #Javascript
聊一聊JavaScript作用域和作用域链
May 03 #Javascript
小白谈谈对JS原型链的理解
May 03 #Javascript
You might like
星际争霸, 教主第一视角, ZvT经典龙蛇演义
2020/03/02 星际争霸
从Web查询数据库之PHP与MySQL篇
2009/09/25 PHP
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
PHP数组操作汇总 php数组的使用技巧
2011/07/17 PHP
phpmyadmin3 安装配置图解教程
2012/03/29 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
PHP图片处理之图片旋转和图片翻转实例
2014/11/19 PHP
PHP实现统计所有字符在字符串中出现次数的方法
2017/10/17 PHP
PHP simplexml_load_file()函数讲解
2019/02/03 PHP
Laravel框架数据库迁移操作实例详解
2020/04/06 PHP
javascript Discuz代码中的msn聊天小功能
2008/05/25 Javascript
JS 对象属性相关(检查属性、枚举属性等)
2015/04/05 Javascript
js添加绑定事件的方法
2016/05/15 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
2016/05/28 Javascript
AngularJS 如何在控制台进行错误调试
2016/06/07 Javascript
详解Javascript百度地图接口开发文档中的类和方法
2017/02/07 Javascript
JavaScript中数组的各种操作的总结(必看篇)
2017/02/13 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
2017/08/16 Javascript
jQuery实现页码跳转式动态数据分页
2017/12/31 jQuery
vuex的module模块用法示例
2018/11/12 Javascript
layui2.0使用table+laypage实现真分页
2019/07/27 Javascript
有关vue 开发钉钉 H5 微应用 dd.ready() 不执行问题及快速解决方案
2020/05/09 Javascript
JavaScript文档加载模式以及元素获取
2020/07/28 Javascript
vue之封装多个组件调用同一接口的案例
2020/08/11 Javascript
[08:44]DOTA2发布会群星聚首 我们都是刀塔人
2014/03/21 DOTA
[36:09]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.24
2019/09/10 DOTA
Python中urllib2模块的8个使用细节分享
2015/01/01 Python
django 通过ajax完成邮箱用户注册、激活账号的方法
2018/04/17 Python
Python使用pandas对数据进行差分运算的方法
2018/12/22 Python
对Python 两大环境管理神器 pyenv 和 virtualenv详解
2018/12/31 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
2019/01/15 Python
Python + Flask 实现简单的验证码系统
2019/10/01 Python
python装饰器相当于函数的调用方式
2019/12/27 Python
CSS3模块的目前的状况分析
2010/02/24 HTML / CSS
歌唱比赛策划方案
2014/06/06 职场文书
个人作风纪律整顿整改措施
2014/10/25 职场文书