总结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 相关文章推荐
11个用于提高排版水平的基于jquery的文字效果插件
Sep 14 Javascript
javascript 二进制运算技巧解析
Nov 27 Javascript
如何防止JavaScript自动插入分号
Nov 05 Javascript
基于javascript实现tab选项卡切换特效调试笔记
Mar 30 Javascript
详解jQuery中的DOM操作
Dec 23 Javascript
基于Bootstrap框架实现图片切换
Mar 10 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
Apr 13 Javascript
bootstrap select下拉搜索插件使用方法详解
Nov 23 Javascript
使用vue中的v-for遍历二维数组的方法
Mar 07 Javascript
如何使用electron-builder及electron-updater给项目配置自动更新
Dec 24 Javascript
vue 引用自定义ttf、otf、在线字体的方法
May 09 Javascript
利用js canvas实现五子棋游戏
Oct 11 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
php5 mysql分页实例代码
2008/04/10 PHP
php 变量定义方法
2009/06/14 PHP
PHP 万年历实现代码
2012/10/18 PHP
深入PHP nl2br()格式化输出的详解
2013/06/05 PHP
如何使用“PHP” 彩蛋进行敏感信息获取
2013/08/07 PHP
php中array_slice和array_splice函数解析
2016/10/18 PHP
php实现统计IP数及在线人数的示例代码
2020/07/22 PHP
用js+xml自动生成表格的东西
2006/12/21 Javascript
Extjs学习笔记之八 继承和事件基础
2010/01/08 Javascript
Jquery通过JSON字符串创建JSON对象
2014/08/24 Javascript
js与C#进行时间戳转换
2014/11/14 Javascript
jquery实现的省市区三级联动
2015/04/02 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
JS生成和下载二维码的代码
2016/12/07 Javascript
jQuery编写网页版2048小游戏
2017/01/06 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
Sublime Text3 配置 NodeJs 环境的方法
2020/05/20 NodeJs
[17:13]DOTA2 HEROS教学视频教你分分钟做大人-斯拉克
2014/06/13 DOTA
利用Python实现图书超期提醒
2016/08/02 Python
再谈Python中的字符串与字符编码(推荐)
2016/12/14 Python
Python实现删除文件中含“指定内容”的行示例
2017/06/09 Python
Python中Selenium模拟JQuery滑动解锁实例
2017/07/26 Python
Python3.5.3下配置opencv3.2.0的操作方法
2018/04/02 Python
python skimage 连通性区域检测方法
2018/06/21 Python
Python2和Python3之间的str处理方式导致乱码的讲解
2019/01/03 Python
pyqt5实现登录界面的模板
2020/05/30 Python
python实例化对象的具体方法
2020/06/17 Python
使用SimpleITK读取和保存NIfTI/DICOM文件实例
2020/07/01 Python
新西兰优惠网站:Treat Me
2019/07/04 全球购物
Java面试题:请说出如下代码的输出结果
2013/04/22 面试题
费用会计岗位职责
2014/01/01 职场文书
优秀老师事迹材料
2014/02/05 职场文书
民主评议教师党员自我评价
2015/03/04 职场文书
交通事故起诉书
2015/05/19 职场文书
2019最新公司租房合同(例文)
2019/07/18 职场文书