likes
comments
collection
share

【源码学习】第17期 | 工作中常用的库之js-cookie

作者站长头像
站长
· 阅读数 21

前言

    日常开发中免不了会接触本地缓存的需求,cookie、localstorage、sessionStorage都有什么区别,该怎么选?下面就学习一下它们的区别,并调试分析常用的js-cookie的源码~

收获清单

  • cookie、localstorage、sessionStorage的应用与区别
  • js-cookie源码

cookie、localstorage、sessionStorage的应用与区别

    这个问题不仅是面试高频考点,也是我们日常工作会经常遇到的,知道它们的区别跟应用场景将有利于我们更好的根据需求选择不同的缓存技术,赶紧码住,它们的区别如下表:

区别cookielocalstoragesessionStorage
生命周期可以设置失效时间,没有设置的话,默认是关闭浏览器后失效除非被手动清除,否则永久保存仅在当前网页会话有效,关闭页面或浏览器后就被清除
存放数据大小不超过4kb5MB左右5MB左右
使用范围同域名下都会共享(子域可以)当前域名下的js脚本不能访问其他域名下的cookie是因为同源策略相同浏览器的同源窗口都会共享通过跳转的同源页面可以共享sessionStorage,同一个页面的不同窗口不可以共享
http请求会自动把当前域名下所有未过期的Cookie一同发送给服务器仅在浏览器中保存,不参与和服务器的通信仅在浏览器中保存,不参与和服务器的通信
应用场景本职工作并非本地存储,而且维持状态,如发送请求时请求头设置登录状态的cookie本地存储工作,一般是不会发生变动的东西,不受不同窗口影响本地存储工作

环境准备

代码下载

git clone https://github.com/js-cookie/js-cookie.git
cd js-cookie
npm install

代码调试

    代码下载下来后教程看README.md,开启调试要看package.jsonscript标签

【源码学习】第17期 | 工作中常用的库之js-cookie 调试截图

【源码学习】第17期 | 工作中常用的库之js-cookie

代码分析

assign 方法(assign.mjs)

    遍历传参,返回所有参数组合而成的对象

export default function (target) {

  for (var i = 1; i < arguments.length; i++) {

    var source = arguments[i]

    for (var key in source) {

      target[key] = source[key]

    }

  }

  return target

}

转换器(converter.mjs)

    读操作使用decodeURIComponent() 函数对 URI 组件进行解码。写操作使用 encodeURIComponent() 函数对 URI 组件进行编码

export default {

  read: function (value) {

    if (value[0] === '"') {

      value = value.slice(1, -1)

    }

    return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent)

  },

  write: function (value) {

    return encodeURIComponent(value).replace(

      /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,

      decodeURIComponent

    )

  }

}

set方法

// key value 属性
function set (name, value, attributes) {
   // 主要是为了判断document是否可用

    if (typeof document === 'undefined') {

      return

    }

    attributes = assign({}, defaultAttributes, attributes)

  

  // 设置了过期时间
    if (typeof attributes.expires === 'number') {

      attributes.expires = new Date(Date.now() + attributes.expires * 864e5)

    }
    // toUTCString()将过期时间根据世界时 (UTC) 把 Date 对象转换为字符串,并返回结果
    if (attributes.expires) {

      attributes.expires = attributes.expires.toUTCString()

    }

  

   // 对cookie的key进行编码
    name = encodeURIComponent(name)

      .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)

      .replace(/[()]/g, escape)

  


    var stringifiedAttributes = ''

    for (var attributeName in attributes) {

      if (!attributes[attributeName]) {

        continue

      }

  


      stringifiedAttributes += '; ' + attributeName

  


      if (attributes[attributeName] === true) {

        continue

      }

      // Considers RFC 6265 section 5.2:

      // ...

      // 3.  If the remaining unparsed-attributes contains a %x3B (";")

      //     character:

      // Consume the characters of the unparsed-attributes up to,

      // not including, the first %x3B (";") character.

      // ...

      stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]

    }

  


    return (document.cookie =

      name + '=' + converter.write(value, name) + stringifiedAttributes)

  }

get 方法

    利用document.cookie获得所有cookie值,遍历取出解码后的指定key的值

function get (name) {

    if (typeof document === 'undefined' || (arguments.length && !name)) {

      return

    }

    // To prevent the for loop in the first place assign an empty array

    // in case there are no cookies at all.

    var cookies = document.cookie ? document.cookie.split('; ') : []

    var jar = {}

    for (var i = 0; i < cookies.length; i++) {

      var parts = cookies[i].split('=')

      var value = parts.slice(1).join('=')
      try {

        var found = decodeURIComponent(parts[0])

        jar[found] = converter.read(value, found)

  


        if (name === found) {

          break

        }

      } catch (e) {}

    }
    return name ? jar[name] : jar

  }

remove 方法

    把对应的key值的对象置空

remove: function (name, attributes) {

        set(

          name,

          '',

          assign({}, attributes, {

            expires: -1

          })

        )

      }

withAttributes 方法

    设置全局默认项

withAttributes: function (attributes) {

        return init(this.converter, assign({}, this.attributes, attributes))

      }

withConverter 方法

    可以覆写编码器

withConverter: function (converter) {

        return init(assign({}, this.converter, converter), this.attributes)

      }

总结

    今天总结了一下cookie、localstorage、sessionStorage的应用与区别,调试分析了js-cookie的关键源码,其实还可以拓展一下cookie的跨域问题,有兴趣的可以了解一下~