JavaScript 对Cookie 操作的封装小结


Posted in Javascript onDecember 31, 2009

Javascript 没有 private , public 访问权限设置的关键字,但是可以通过一定的技巧来模拟出相同的结果.
首先我们来看下面一行代码:
var i = (1, 2, 3, 4, 5);
变量 i 最后的结果为 5.
这是逗号操作符的结果,也就是说返回最后的一个值,小括号改变了这行代码的优先级,否则 var i = 1, 2, 3, 4, 5; 会报错缺少标识符.

var i = (1, 2, 3, 4, function(){ return 5 * 5;});
变量 i 最后的结果为 一个函数, 返回结果 25.
这就是Javascript 的灵活之处,能够赋值任意类型而不必提前声明.现在我们完全可以进行如下调用:

i();
alert( i() );
来获得返回25的一次方法调用.

我们继续, 变量 i 是通过赋值符来获取函数的引用的, 也就是说在等号右边的小括号运算完后返回的最后一个结果的引用还在,虽然我们无法显示调用,但它确实存在,如果要不通过变量的引用而调用呢?

(1, 2, 3, 4, function(){ alert(5 * 5);})()
上面的代码执行后,弹出一个消息框,显示25.
为了显示方便,我将上个例子的函数改为弹出消息框了.
两对小括号 () (); 前面一对表示返回一个结果,如果该结果为一个函数,由第二对小括号发生调用.
也就是通过前面一对括号发生匿名函数的引用,以便在下面进行引用.这就是对匿名函数的调用.
关于更多匿名函数的使用可以参考文尾的引用连接.

闭包产生的原因是因为作用域的不同,子作用域引用了父作用域的变量,而返回子作用域,父作用域按理来说执行完毕后该销毁掉了,只是子作用域一直存在,且一直握有父作用域的引用,所以才一直保留.
来看下面的代码

function parent() { 
var a = 1; 
function child(){ 
var b = 2; 
alert(a); 
alert(b); 
} 
}

父函数 parent 中包含了一个 child 子函数,在子函数中有一个对父函数中 a 变量的引用(输出其值).
我们来让父函数执行完后返回其声明的子函数
function parent() { 
var a = 1; 
function child(){ 
var b = 2; 
alert(a); 
alert(b); 
} 
return child; 
} 
var t = parent(); 
t();

在10行中, 我们执行了parent 函数,返回了在函数内部声明的函数 child,这时变量 t 持有该返回对象(此时是一个可以执行的函数)的引用,在11行代码中我们调用了它.结果分别输出了 1 和 2.
注意,输出 2, 是因为我们在子函数体内声明了一个变量,而输出 1, 我们在该函数体内并没有相应的定义变量 a ,而是发生了对父函数里的变量的引用,也就是说引用了父作用域的变量.
而此时又能能够完成输出的,也就是说变量 a 还存在.可是我们无法直接对其引用 (比如 parent.a),因为函数已经执行完毕,没有了其相应的引用,我们只能通过所返回的子函数的引用来进行访问.
假如我又在父函数中声明了其他的变量呢? 结果是一样的,子函数能够访问,而如果子函数并不返回相应的引用的话,我们根本无法从外部访问到.这就形成了闭包.

闭包能够干些什么呢?如果你有一个不想让外部随意修改的变量该怎么做?那就去使用闭包.

myObj = {}; //声明一个全局变量,它是一个window对象的属性(window.myObj) 
(function(){ 
var i = 4; 
myObj = { //引用全局变量,对其进行赋值 
getI : function() { //get方法,一个函数 
return i; 
}, 
setI : function(val) { //set方法,限制值的设定 
if(val > 100) { 
alert("i connt > 100"); 
return; 
} 
i = val; 
} 
} 
})(); //匿名函数的调用,由于也是一个函数,所以作为一个子作用域,在执行完之后销毁,避免代码污染 
myObj.setI(5); //成功 
myObj.setI(101); //失败 
alert(myObj.getI()); 
alert(myObj.i); //错误,没有该属性

至此我们简单的实现了public 访问权限以及 private 访问权限 (也就给你想给你的,不给你不想给你的)

在页面中,我们通常使用 document.cookie 属性来访问,对其赋新值就会创建一个新的Cookie,一个Cookie通常具有五个属性:value (存储的值), date (UTC格式的时间,代表什么时间过期, domain (域,Cookie的所有者), Path (子目录).
而在平常的开发中,如果仅仅使用 document.cookie 属性进行访问,会很麻烦,因为只能向其赋值字符串,并且在读取后还要进行字符串切割,才能获取指定变量名称的值.document.cookie 读取时,返回的是所有赋值的值,而不包括过期时间,域之类的信息,只能再次独设置.
下面就附上代码,全部封装到Cookie全局对象中,暴露出几个方法.
Get : 放回指定所有cookie字符串.
Set : 设置cookie 字符串.
Clear : 清除所有cookie对象.
GetDayTime : 获取指定距今val天的Date对象.
Write : 写cookie.已重载.详见代码.
Query : 查询cookie. 已重载.详见代码.
Update : 修改cookie.
Delete : 删除cookie.

代码1-7

Cookie = {}; 
/* 
* Date对象的setTime方法是设置距离1970-01-01以来的毫秒数,设置到对象里去,返回的是据那以后的毫秒数而不是原对象. 
* 如果Cookie 不设置 expires 属性,或者expires 时间比本地时间少,那么将会在下一次浏览时过期. 
* document.cookie 对象返回的是所有值的字符串形式,不包含 expires 或者其他. 
* 
*/ 
(function() { 
var nDay = 24 * 60 * 60 * 1000; 
var isString = function(v) { 
return typeof v === "string"; 
} 
var isArray = function(v) { 
return Object.prototype.toString.apply(v) == "[object Array]"; 
} 
var isObject = function(v) { 
return v && typeof v == "object"; 
} 
var isDate = function(v) { 
return Object.prototype.toString.apply(v) == "[object Date]"; 
} 
var getTime = function() { 
return new Date().getTime(); 
} 
var trim = function(val) { 
return (val || "").replace(/^\s+|\s+$/g, ""); 
} 
var tryEval = function(val) { 
var Obj, e; 
try { 
Obj = eval(val); 
} catch (e) { 
Obj = val; 
} 
return Obj; 
} 
var ObjectToString = function(o) { 
var tstr = "{"; 
for (var v in o) { 
if (isArray(o[v])) { 
tstr += v + ":" + ArrayToString(o[v]) + ","; 
} else if (isObject(o[v])) { 
tstr += v + ":" + ObjectToString(o[v]) + ","; 
} else if (isString(o[v])) { 
tstr += v + ":\"" + o[v].toString() + "\","; 
} else { 
tstr += v + ":" + o[v].toString() + ","; 
} 
} 
return tstr.slice(0, -1) + "}"; 
} 
var ArrayToString = function(o) { 
var tstr = "["; 
for (var v in o) { 
if (isArray(o[v])) { 
tstr += ArrayToString(o[v]) + ","; 
} else if (isObject(o[v])) { 
tstr += ObjectToString(o[v]) + ","; 
} else { 
tstr += o[v].toString() + ","; 
} 
} 
return tstr.slice(0, -1) + "]"; ; 
} 
Cookie = { 
Get: function() { 
return document.cookie; 
}, 
Set: function(val) { 
document.cookie = val; 
}, 
Clear: function() { 
var temp = this.Query(); 
var o; 
for (o in temp) { 
this.Delete(o); 
} 
}, 
GetDayTime: function(val) { 
var texpires = new Date(); 
texpires.setTime(texpires.getTime() + val * nDay); 
return texpires; 
}, 
Write: function() { 
/* 
* Cookie.Write(Object); 写入对象,名称为main; 
* Cookie.Write(varname, Object); varname:变量名, Object:写入对象; 
* Cookie.Write(Object, Date); Object:写入对象, Date:过期时间; 
* Cookie.Write(varname, Object, Date); varname:变量名, Object:写入对象, Date:过期时间; 
* Cookie.Write(varname, Object, Date, Domain, Path); varname:变量名, Object:写入对象, Date:过期时间, Domain:域, Path: 子目录; 
*/ 
if (arguments.length == 1) { 
var tvalue = arguments[0]; 
var tstr = ""; 
var texpires = new Date(); texpires.setTime(texpires.getTime() + 1 * nDay); 
if (isArray(tvalue)) { 
tstr = ArrayToString(tvalue); 
} else if (isObject(tvalue)) { 
tstr = ObjectToString(tvalue); 
} else { 
tstr = tvalue.toString(); 
} 
tstr = "main=" + escape(tstr) + ";expires=" + texpires.toGMTString() + ";"; 
} else if (arguments.length == 2) { 
var tname, tvalue, texpires, tstr = ""; 
if (isDate(arguments[1])) { 
tname = "main"; 
tvalue = arguments[0]; 
texpires = arguments[1]; 
} else { 
tname = arguments[0]; 
tvalue = arguments[1]; 
texpires = new Date(); texpires.setTime(texpires.getTime() + 1 * nDay); 
} 
if (isArray(tvalue)) { 
tstr += ArrayToString(tvalue); 
} else if (isObject(tvalue)) { 
tstr += ObjectToString(tvalue); 
} else { 
tstr = tvalue.toString(); 
} 
tstr = tname + "=" + escape(tvalue) + ";expires=" + texpires.toGMTString() + ";"; 
} else if (arguments.length == 3) { 
var tname = arguments[0], tvalue = arguments[1], texpires = arguments[2], tstr = ""; 
if (isArray(tvalue)) { 
tstr = ArrayToString(tvalue); 
} else if (isObject(tvalue)) { 
tstr = ObjectToString(tvalue); 
} else { 
tstr = tvalue.toString(); 
} 
tstr = tname + "=" + escape(tvalue) + ";expires=" + texpires.toGMTString() + ";"; 
} else if (arguments.length == 5) { 
var tname = arguments[0], tvalue = arguments[1], texpires = arguments[2], tdomain = arguments[3], tpath = arguments[4], tstr = ""; 
if (isArray(tvalue)) { 
tstr = ArrayToString(tvalue); 
} else if (isObject(tvalue)) { 
tstr = ObjectToString(tvalue); 
} else { 
tstr = tvalue.toString(); 
} 
tstr = tname + "=" + escape(tvalue) + ";expires=" + texpires.toGMTString() + ";domain=" + tdomain + ";path=" + tpath + ";"; 
} 
alert(tstr); 
this.Set(tstr); 
}, 
Query: function() { 
/* 
* Cookie.Query(); 返回所有Cookie值组成的Object; 
* Cookie.Query(string); 返回指定名称的Object; 失败则返回 undefined; 
* Cookie.Query(string, Object); 为指定对象写入指定名称的Object,并返回; 失败则返回 undefined; 
*/ 
var tname = tvalue = "", tright = -1; 
var tstr = this.Get(); 
var tObj = {}; 
if (arguments.length == 0) { 
var i = 0; 
do { 
tname = trim(tstr.slice(i, tstr.indexOf("=", i))); 
tright = tstr.indexOf(";", i); 
if (tright == -1) { 
tvalue = unescape(tstr.slice(tstr.indexOf("=", i) + 1, tstr.length)); 
} else { 
tvalue = unescape(tstr.slice(tstr.indexOf("=", i) + 1, tright)); 
} 
tObj[tname] = tryEval(tvalue); 
i = tstr.indexOf(";", i) == -1 ? -1 : tstr.indexOf(";", i) + 1; 
} while (i != -1); 
} else { 
tname = arguments[0]; 
if (tstr.indexOf(tname) == -1) return undefined; 
var i = tstr.indexOf(tname); 
tname = trim(tstr.slice(i, tstr.indexOf("=", i))); 
tright = tstr.indexOf(";", tstr.indexOf(tname)) == -1 ? tstr.length : tstr.indexOf(";", tstr.indexOf(tname)); 
tvalue = unescape(tstr.slice(tstr.indexOf(tname) + tname.length + 1, tright)); 
if (arguments.length == 1) { 
tObj = tryEval(tvalue); 
} else if (arguments.length == 2) { 
tObj = arguments[1]; 
tObj[tname] = tryEval(tvalue); 
} 
} 
return tObj; 
}, 
Update: function() { 
return this.Write.apply(this, arguments); 
}, 
Delete: function() { 
if (arguments.length == 1) { 
var varname = arguments[0]; 
if (this.Query(varname)) { 
this.Update(varname, "", new Date(1970, 01, 01)); 
} 
} 
} 
}

其中有一个从字符串eval 成对象的执行,以及从Object 或者 Array 对象获得对应字符串形式的功能函数,模拟了一些JSON的操作.当然,并不能存储所有的JavaScript 对象,仅仅满足一部分,我已经感觉够用了.

个人理解有限,请各位多多指教.
Javascript的匿名函数 : http://dancewithnet.com/2008/05/07/javascript-anonymous-function/
Javascript的闭包 : http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html
Cookie 文件的格式 : http://www.cnblogs.com/sephil/archive/2008/05/06/cookiefmt.html

Javascript 相关文章推荐
使用SyntaxHighlighter实现HTML高亮显示代码的方法
Feb 04 Javascript
js 创建书签小工具之理论
Feb 25 Javascript
JavaScript 学习笔记之基础中的基础
Jan 13 Javascript
jQuery手机浏览器中拖拽动作的艰难性分析
Feb 04 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
Mar 22 Javascript
AngularJS基础 ng-href 指令用法
Aug 01 Javascript
Angular2  NgModule 模块详解
Oct 19 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
Mar 10 Javascript
谈谈vue中mixin的一点理解
Dec 12 Javascript
详解swipe使用及竖屏页面滚动方法
Jun 28 Javascript
vue-cli3+ts+webpack实现多入口多出口功能
May 30 Javascript
JS实现简单随机3D骰子
Oct 24 Javascript
Javascript的闭包
Dec 31 #Javascript
javascript Onunload与Onbeforeunload使用小结
Dec 31 #Javascript
JavaScript 常用函数
Dec 30 #Javascript
jQuery的三种$()
Dec 30 #Javascript
jquery UI 1.72 之datepicker
Dec 29 #Javascript
用js做一个小游戏平台 (一)
Dec 29 #Javascript
js 学习笔记(三)
Dec 29 #Javascript
You might like
PHP时间格式控制符对照表分享
2013/07/23 PHP
彻底删除thinkphp3.1案例blog标签的方法
2014/12/05 PHP
PHP函数按引用传递参数及函数可选参数用法示例
2018/06/04 PHP
asp 取文本框名称代码
2008/12/02 Javascript
JQuery 选择器 xpath 语法应用
2010/05/13 Javascript
THREE.JS入门教程(6)创建自己的全景图实现步骤
2013/01/25 Javascript
将form表单中的元素转换成对象的方法适用表单提交
2014/05/02 Javascript
实用框架(iframe)操作代码
2014/10/23 Javascript
js判断手机端(Android手机还是iPhone手机)
2015/07/22 Javascript
js实现获取当前时间是本月第几周的方法
2015/08/11 Javascript
JavaScript tab选项卡插件实例代码
2016/02/23 Javascript
微信小程序 教程之模块化
2016/10/17 Javascript
Vue.js第一天学习笔记(数据的双向绑定、常用指令)
2016/12/01 Javascript
Bootstrap 下拉多选框插件Bootstrap Multiselect
2017/01/22 Javascript
node的process以及child_process模块学习笔记
2018/03/06 Javascript
js实现图片上传并预览功能
2018/08/06 Javascript
详解ESLint在Vue中的使用小结
2018/10/15 Javascript
JavaScript 防盗链的原理以及破解方法
2020/12/29 Javascript
[03:12]完美世界DOTA2联赛PWL DAY6集锦
2020/11/05 DOTA
python利用elaphe制作二维条形码实现代码
2012/05/25 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
TensorBoard 计算图的可视化实现
2020/02/15 Python
非常漂亮的CSS3百叶窗焦点图动画
2016/02/24 HTML / CSS
Clarks鞋法国官方网站:英国其乐鞋品牌
2018/02/11 全球购物
外贸业务员工作职责
2014/01/06 职场文书
大学校庆邀请函
2014/01/11 职场文书
酒店营销策划方案
2014/02/07 职场文书
小露珠教学反思
2014/04/30 职场文书
农业开发项目建议书
2014/05/16 职场文书
安全施工标语
2014/06/07 职场文书
教师职业道德事迹材料
2014/08/18 职场文书
2014年小班保育员工作总结
2014/12/23 职场文书
公司财务部岗位职责
2015/04/14 职场文书
加薪通知
2015/04/25 职场文书
党员承诺书范文2015
2015/04/27 职场文书
如何用RabbitMQ和Swoole实现一个异步任务系统
2021/05/29 PHP