js-cookie v2.2.1源码解析

一、代码主体结构

 

二、源码分析

1.  结构代码

;(function(factory){ // 立即执行函数
   ...
})(function(){
    ....
}));

 

2. 立即执行函数内容代码分析

 1     var registeredInModuleLoader;   // 变量定义是否是模块形式加载
 2     if (typeof define === 'function' && define.amd) {
 3         define(factory);
 4         registeredInModuleLoader = true;
 5     }
 6     if (typeof exports === 'object') {
 7         module.exports = factory();
 8         registeredInModuleLoader = true;
 9     }
10     if (!registeredInModuleLoader) {  // 非模块形式加载, 直接赋值 window.Cookies
11         var OldCookies = window.Cookies;
12         var api = window.Cookies = factory();
13         api.noConflict = function () {  // 解决冲突,定义函数使用默认的window.Cookies
14             window.Cookies = OldCookies;
15             return api;
16         };
17     }

  

3. 函数代码主体分析

a、辅助函数

 1 // 将参数集合变成map对象形式 [{'a': 'value'}]   ---> { '0': { 'a': 'value' } }
 2     function extend () {
 3         var i = 0;
 4         var result = {};
 5         for (; i < arguments.length; i++) {
 6             var attributes = arguments[ i ];
 7             for (var key in attributes) {
 8                 result[key] = attributes[key];
 9             }
10         }
11         return result;
12     }
13     console(extend( ['a':'1'] )); 
14     
15     // URI解码 %23 --> #
16     function decode (s) { 
17         return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
18     }

 

b、核心函数

 

 

 

 1 function set(key, value, attributes) {
 2         if (typeof document === 'undefined') {
 3             return;
 4         }
 5 
 6         attributes = extend({
 7             path: '/'
 8         }, api.defaults, attributes);
 9 
10         // 检查是否设置过期时长
11         if (typeof attributes.expires === 'number') {
12             attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
13         }
14 
15         // IE不支持max-age,故而使用 expires
16         attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
17         
18         // 将json转成字符串格式
19         try {
20             var result = JSON.stringify(value);
21             if (/^[\{\[]/.test(result)) {
22                 value = result;
23             }
24         } catch (e) {}
25         
26         // 检查converter是否能直接写入,不能则先URI编码再写入
27         //  "=13&123=中文" --> "=13&123=%E4%B8%AD%E6%96%87"
28         value = converter.write ?
29             converter.write(value, key) :
30             encodeURIComponent(String(value))
31             .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
32         
33         // key也URI编码    
34         key = encodeURIComponent(String(key))
35             .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
36             .replace(/[\(\)]/g, escape);
37         
38         
39         // 设置document.cookie = key+'='+value+'; attr';
40         var stringifiedAttributes = '';
41         for (var attributeName in attributes) {
42             if (!attributes[attributeName]) {
43                 continue;
44             }
45             stringifiedAttributes += '; ' + attributeName;
46             if (attributes[attributeName] === true) {
47                 continue;
48             }
49 
50             // Considers RFC 6265 section 5.2:
51             // ...
52             // 3.  If the remaining unparsed-attributes contains a %x3B (";")
53             //     character:
54             // Consume the characters of the unparsed-attributes up to,
55             // not including, the first %x3B (";") character.
56             // ...
57             stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
58         }
59 
60         return (document.cookie = key + '=' + value + stringifiedAttributes);
61 }

 

  1 // 初始化一个cookie对象
  2 function init(converter) {
  3     
  4     // 定义空函数
  5     function api() {}
  6 
  7     // set函数赋值
  8     function set(key, value, attributes) {
  9         if (typeof document === 'undefined') {
 10             return;
 11         }
 12 
 13         attributes = extend({
 14             path: '/'
 15         }, api.defaults, attributes);
 16 
 17         if (typeof attributes.expires === 'number') {
 18             attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
 19         }
 20 
 21         // We're using "expires" because "max-age" is not supported by IE
 22         attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
 23 
 24         try {
 25             var result = JSON.stringify(value);
 26             if (/^[\{\[]/.test(result)) {
 27                 value = result;
 28             }
 29         } catch (e) {}
 30 
 31         value = converter.write ?
 32             converter.write(value, key) :
 33             encodeURIComponent(String(value))
 34             .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
 35 
 36         key = encodeURIComponent(String(key))
 37             .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
 38             .replace(/[\(\)]/g, escape);
 39 
 40         var stringifiedAttributes = '';
 41         for (var attributeName in attributes) {
 42             if (!attributes[attributeName]) {
 43                 continue;
 44             }
 45             stringifiedAttributes += '; ' + attributeName;
 46             if (attributes[attributeName] === true) {
 47                 continue;
 48             }
 49 
 50             // Considers RFC 6265 section 5.2:
 51             // ...
 52             // 3.  If the remaining unparsed-attributes contains a %x3B (";")
 53             //     character:
 54             // Consume the characters of the unparsed-attributes up to,
 55             // not including, the first %x3B (";") character.
 56             // ...
 57             stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
 58         }
 59 
 60         return (document.cookie = key + '=' + value + stringifiedAttributes);
 61     }
 62     
 63     //  获取key的值
 64     function get(key, json) {
 65         if (typeof document === 'undefined') {
 66             return;
 67         }
 68 
 69         var jar = {};
 70         // To prevent the for loop in the first place assign an empty array
 71         // in case there are no cookies at all.
 72         var cookies = document.cookie ? document.cookie.split('; ') : [];
 73         var i = 0;
 74 
 75         for (; i < cookies.length; i++) {
 76             var parts = cookies[i].split('=');
 77             var cookie = parts.slice(1).join('=');
 78 
 79             if (!json && cookie.charAt(0) === '"') {
 80                 cookie = cookie.slice(1, -1);
 81             }
 82 
 83             try {
 84                 var name = decode(parts[0]);
 85                 cookie = (converter.read || converter)(cookie, name) ||
 86                     decode(cookie);
 87 
 88                 if (json) {
 89                     try {
 90                         cookie = JSON.parse(cookie);
 91                     } catch (e) {}
 92                 }
 93 
 94                 jar[name] = cookie;
 95 
 96                 if (key === name) {
 97                     break;
 98                 }
 99             } catch (e) {}
100         }
101 
102         return key ? jar[key] : jar;
103     }
104 
105     // 为api绑定set属性
106     api.set = set;
107     
108     // 为api绑定get
109     api.get = function(key) {
110         return get(key, false /* read as raw */ );
111     };
112     
113     // 为api绑定getJSON
114     api.getJSON = function(key) {
115         return get(key, true /* read as json */ );
116     };
117     
118     // 为api绑定remove
119     api.remove = function(key, attributes) {
120         set(key, '', extend(attributes, {
121             expires: -1
122         }));
123     };
124 
125     // 为api定义默认配置
126     api.defaults = {};
127 
128     // 定义withConverter属性指向init
129     api.withConverter = init;
130 
131     // 返回api
132     return api;
133 }
134 
135 // 获取cookie的key; 找到cookie中对应的key取出value值
136 function get(key, json) {
137     if (typeof document === 'undefined') {
138         return;
139     }
140 
141     var jar = {};
142     // To prevent the for loop in the first place assign an empty array
143     // in case there are no cookies at all.
144     var cookies = document.cookie ? document.cookie.split('; ') : [];
145     var i = 0;
146 
147     for (; i < cookies.length; i++) {
148         var parts = cookies[i].split('=');
149         var cookie = parts.slice(1).join('=');
150 
151         if (!json && cookie.charAt(0) === '"') {
152             cookie = cookie.slice(1, -1);
153         }
154 
155         try {
156             var name = decode(parts[0]);
157             cookie = (converter.read || converter)(cookie, name) ||
158                 decode(cookie);
159 
160             if (json) {
161                 try {
162                     cookie = JSON.parse(cookie);
163                 } catch (e) {}
164             }
165 
166             jar[name] = cookie;
167 
168             if (key === name) {
169                 break;
170             }
171         } catch (e) {}
172     }
173 
174     return key ? jar[key] : jar;
175 }

 

 1 // 为api绑定set属性
 2     api.set = set;
 3     
 4     // 为api绑定get, 返回基本数据类型
 5     api.get = function(key) {
 6         return get(key, false /* read as raw */ );
 7     };
 8     
 9     // 为api绑定getJSON, 返回json的值
10     api.getJSON = function(key) {
11         return get(key, true /* read as json */ );
12     };
13     
14     // 为api绑定remove, 设置key的expires为当前时间,则会立即过期
15     api.remove = function(key, attributes) {
16         set(key, '', extend(attributes, {
17             expires: -1
18         }));
19     };
20 
21     // 为api定义默认配置
22     api.defaults = {};

 c. 细节

 

1 // 根据path地址 / 来确定cookie所属作用范围; 默认 / 所有page都可以获取到cookie
2 attributes = extend({
3     path: '/'
4 }, api.defaults, attributes);

https://github.com/js-cookie/js-cookie
posted @ 2020-12-14 10:08  pengsn  阅读(158)  评论(0编辑  收藏  举报