总结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 相关文章推荐
jQuery源码分析-05异步队列 Deferred 使用介绍
Nov 14 Javascript
用js来定义浏览器中一个左右浮动元素相对于页面主体宽度的位置的函数
Jan 21 Javascript
基于jquery的文本框与autocomplete结合使用(asp.net+json)
May 30 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
May 12 Javascript
JavaScript操作表单实例讲解(上)
Jun 20 Javascript
JavaScript鼠标事件,点击鼠标右键,弹出div的简单实例
Aug 03 Javascript
JavaScript lodash常见用法系列小结
Aug 24 Javascript
《javascript少儿编程》location术语总结
May 27 Javascript
layui 设置table 行的高度方法
Aug 17 Javascript
基于vue-upload-component封装一个图片上传组件的示例
Oct 16 Javascript
vue-cli3.0+element-ui上传组件el-upload的使用
Dec 03 Javascript
基于vue实现简易打地鼠游戏
Aug 21 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
PHP脚本的10个技巧(1)
2006/10/09 PHP
PHP版微信公众平台红包API
2015/04/02 PHP
php限制文件下载速度的代码
2015/10/20 PHP
破解Session cookie的方法
2006/07/28 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
2015/06/03 Javascript
JQuery实现样式设置、追加、移除与切换的方法
2015/06/11 Javascript
关于vue.js弹窗组件的知识点总结
2016/09/11 Javascript
jQuery实现导航高亮的方法【附demo源码下载】
2016/11/09 Javascript
js手机号批量滚动抽奖实现代码
2020/04/17 Javascript
js阻止默认右键的下拉菜单方法
2018/01/02 Javascript
使用Vue生成动态表单
2019/11/26 Javascript
Element Badge标记的使用方法
2020/07/27 Javascript
使用Protocol Buffers的C语言拓展提速Python程序的示例
2015/04/16 Python
python实现简单的socket server实例
2015/04/29 Python
Python函数可变参数定义及其参数传递方式实例详解
2015/05/25 Python
在双python下设置python3为默认的方法
2018/10/31 Python
python实现全盘扫描搜索功能的方法
2019/02/14 Python
Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)
2020/02/05 Python
TensorFlow2.0矩阵与向量的加减乘实例
2020/02/07 Python
aws 通过boto3 python脚本打pach的实现方法
2020/05/10 Python
python 实现性别识别
2020/11/21 Python
澳大利亚在线消费电子产品商店:TobyDeals
2020/01/05 全球购物
5个HTML5的常用本地存储方式详解与介绍
2021/03/27 HTML / CSS
艺术爱好者的自我评价分享
2013/10/08 职场文书
应届生人事助理求职信
2013/11/09 职场文书
面临毕业的毕业生自荐书范文
2014/02/05 职场文书
幼儿园2014年度工作总结
2014/11/10 职场文书
出纳年终工作总结2014
2014/12/05 职场文书
2015年团队工作总结范文
2015/05/04 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
出生证明格式
2015/06/15 职场文书
Python实现简繁体转换
2021/06/07 Python
Nginx使用Lua模块实现WAF的原理解析
2021/09/04 Servers
Java使用JMeter进行高并发测试
2021/11/23 Java/Android
mysql中整数数据类型tinyint详解
2021/12/06 MySQL
Python find()、rfind()方法及作用
2022/12/24 Python