JavaScript 對Cookie 操作的封裝小結

來源:互聯網
上載者:User

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.