匿名函數(shù)
閉包的產(chǎn)生
JavaScript實(shí)現(xiàn)private 以及 public 訪問(wèn)權(quán)限
document.cookie 的操作
Javascript 沒(méi)有 private , public 訪問(wèn)權(quán)限設(shè)置的關(guān)鍵字,但是可以通過(guò)一定的技巧來(lái)模擬出相同的結(jié)果.
首先我們來(lái)看下面一行代碼:
var i = (1, 2, 3, 4, 5);
變量 i 最后的結(jié)果為 5.
這是逗號(hào)操作符的結(jié)果,也就是說(shuō)返回最后的一個(gè)值,小括號(hào)改變了這行代碼的優(yōu)先級(jí),否則 var i = 1, 2, 3, 4, 5; 會(huì)報(bào)錯(cuò)缺少標(biāo)識(shí)符.
var i = (1, 2, 3, 4, function(){ return 5 * 5;});
變量 i 最后的結(jié)果為 一個(gè)函數(shù), 返回結(jié)果 25.
這就是Javascript 的靈活之處,能夠賦值任意類型而不必提前聲明.現(xiàn)在我們完全可以進(jìn)行如下調(diào)用:
i();
alert( i() );
來(lái)獲得返回25的一次方法調(diào)用.
我們繼續(xù), 變量 i 是通過(guò)賦值符來(lái)獲取函數(shù)的引用的, 也就是說(shuō)在等號(hào)右邊的小括號(hào)運(yùn)算完后返回的最后一個(gè)結(jié)果的引用還在,雖然我們無(wú)法顯示調(diào)用,但它確實(shí)存在,如果要不通過(guò)變量的引用而調(diào)用呢?
(1, 2, 3, 4, function(){ alert(5 * 5);})()
上面的代碼執(zhí)行后,彈出一個(gè)消息框,顯示25.
為了顯示方便,我將上個(gè)例子的函數(shù)改為彈出消息框了.
兩對(duì)小括號(hào) () (); 前面一對(duì)表示返回一個(gè)結(jié)果,如果該結(jié)果為一個(gè)函數(shù),由第二對(duì)小括號(hào)發(fā)生調(diào)用.
也就是通過(guò)前面一對(duì)括號(hào)發(fā)生匿名函數(shù)的引用,以便在下面進(jìn)行引用.這就是對(duì)匿名函數(shù)的調(diào)用.
關(guān)于更多匿名函數(shù)的使用可以參考文尾的引用連接.
閉包產(chǎn)生的原因是因?yàn)樽饔糜虻牟煌?子作用域引用了父作用域的變量,而返回子作用域,父作用域按理來(lái)說(shuō)執(zhí)行完畢后該銷毀掉了,只是子作用域一直存在,且一直握有父作用域的引用,所以才一直保留.
來(lái)看下面的代碼
1 function parent() {
2 var a = 1;
3 function child(){
4 var b = 2;
5 alert(a);
6 alert(b);
7 }
8 }
父函數(shù) parent 中包含了一個(gè) child 子函數(shù),在子函數(shù)中有一個(gè)對(duì)父函數(shù)中 a 變量的引用(輸出其值).
我們來(lái)讓父函數(shù)執(zhí)行完后返回其聲明的子函數(shù)
1 function parent() {
2 var a = 1;
3 function child(){
4 var b = 2;
5 alert(a);
6 alert(b);
7 }
8 return child;
9 }
10 var t = parent();
11 t();
在10行中, 我們執(zhí)行了parent 函數(shù),返回了在函數(shù)內(nèi)部聲明的函數(shù) child,這時(shí)變量 t 持有該返回對(duì)象(此時(shí)是一個(gè)可以執(zhí)行的函數(shù))的引用,在11行代碼中我們調(diào)用了它.結(jié)果分別輸出了 1 和 2.
注意,輸出 2, 是因?yàn)槲覀冊(cè)谧雍瘮?shù)體內(nèi)聲明了一個(gè)變量,而輸出 1, 我們?cè)谠摵瘮?shù)體內(nèi)并沒(méi)有相應(yīng)的定義變量 a ,而是發(fā)生了對(duì)父函數(shù)里的變量的引用,也就是說(shuō)引用了父作用域的變量.
而此時(shí)又能能夠完成輸出的,也就是說(shuō)變量 a 還存在.可是我們無(wú)法直接對(duì)其引用 (比如 parent.a),因?yàn)楹瘮?shù)已經(jīng)執(zhí)行完畢,沒(méi)有了其相應(yīng)的引用,我們只能通過(guò)所返回的子函數(shù)的引用來(lái)進(jìn)行訪問(wèn).
假如我又在父函數(shù)中聲明了其他的變量呢? 結(jié)果是一樣的,子函數(shù)能夠訪問(wèn),而如果子函數(shù)并不返回相應(yīng)的引用的話,我們根本無(wú)法從外部訪問(wèn)到.這就形成了閉包.
閉包能夠干些什么呢?如果你有一個(gè)不想讓外部隨意修改的變量該怎么做?那就去使用閉包.
1 myObj = {}; //聲明一個(gè)全局變量,它是一個(gè)window對(duì)象的屬性(window.myObj)
2 (function(){
3 var i = 4;
4 myObj = { //引用全局變量,對(duì)其進(jìn)行賦值
5 getI : function() { //get方法,一個(gè)函數(shù)
6 return i;
7 },
8 setI : function(val) { //set方法,限制值的設(shè)定
9 if(val > 100) {
10 alert("i connt > 100");
11 return;
12 }
13 i = val;
14 }
15 }
16 })(); //匿名函數(shù)的調(diào)用,由于也是一個(gè)函數(shù),所以作為一個(gè)子作用域,在執(zhí)行完之后銷毀,避免代碼污染
17 myObj.setI(5); //成功
18 myObj.setI(101); //失敗
19 alert(myObj.getI());
20 alert(myObj.i); //錯(cuò)誤,沒(méi)有該屬性
至此我們簡(jiǎn)單的實(shí)現(xiàn)了public 訪問(wèn)權(quán)限以及 private 訪問(wèn)權(quán)限 (也就給你想給你的,不給你不想給你的)
在頁(yè)面中,我們通常使用 document.cookie 屬性來(lái)訪問(wèn),對(duì)其賦新值就會(huì)創(chuàng)建一個(gè)新的Cookie,一個(gè)Cookie通常具有五個(gè)屬性:value (存儲(chǔ)的值), date (UTC格式的時(shí)間,代表什么時(shí)間過(guò)期, domain (域,Cookie的所有者), Path (子目錄).
而在平常的開(kāi)發(fā)中,如果僅僅使用 document.cookie 屬性進(jìn)行訪問(wèn),會(huì)很麻煩,因?yàn)橹荒芟蚱滟x值字符串,并且在讀取后還要進(jìn)行字符串切割,才能獲取指定變量名稱的值.document.cookie 讀取時(shí),返回的是所有賦值的值,而不包括過(guò)期時(shí)間,域之類的信息,只能再次獨(dú)設(shè)置.