匿名函數
閉包的產生
JavaScript實現private 以及 public 訪問權限
document.cookie 的操作
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.
為了顯示方便,我將上個例子的函數改為彈出消息框了.
兩對小括號 () (); 前面一對表示返回一個結果,如果該結果為一個函數,由第二對小括號發生調用.
也就是通過前面一對括號發生匿名函數的引用,以便在下面進行引用.這就是對匿名函數的調用.
關于更多匿名函數的使用可以參考文尾的引用連接.
閉包產生的原因是因為作用域的不同,子作用域引用了父作用域的變量,而返回子作用域,父作用域按理來說執行完畢后該銷毀掉了,只是子作用域一直存在,且一直握有父作用域的引用,所以才一直保留.
來看下面的代碼
1 function parent() {
2 var a = 1;
3 function child(){
4 var b = 2;
5 alert(a);
6 alert(b);
7 }
8 }
父函數 parent 中包含了一個 child 子函數,在子函數中有一個對父函數中 a 變量的引用(輸出其值).
我們來讓父函數執行完后返回其聲明的子函數
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行中, 我們執行了parent 函數,返回了在函數內部聲明的函數 child,這時變量 t 持有該返回對象(此時是一個可以執行的函數)的引用,在11行代碼中我們調用了它.結果分別輸出了 1 和 2.
注意,輸出 2, 是因為我們在子函數體內聲明了一個變量,而輸出 1, 我們在該函數體內并沒有相應的定義變量 a ,而是發生了對父函數里的變量的引用,也就是說引用了父作用域的變量.
而此時又能能夠完成輸出的,也就是說變量 a 還存在.可是我們無法直接對其引用 (比如 parent.a),因為函數已經執行完畢,沒有了其相應的引用,我們只能通過所返回的子函數的引用來進行訪問.
假如我又在父函數中聲明了其他的變量呢? 結果是一樣的,子函數能夠訪問,而如果子函數并不返回相應的引用的話,我們根本無法從外部訪問到.這就形成了閉包.
閉包能夠干些什么呢?如果你有一個不想讓外部隨意修改的變量該怎么做?那就去使用閉包.
1 myObj = {}; //聲明一個全局變量,它是一個window對象的屬性(window.myObj)
2 (function(){
3 var i = 4;
4 myObj = { //引用全局變量,對其進行賦值
5 getI : function() { //get方法,一個函數
6 return i;
7 },
8 setI : function(val) { //set方法,限制值的設定
9 if(val > 100) {
10 alert("i connt > 100");
11 return;
12 }
13 i = val;
14 }
15 }
16 })(); //匿名函數的調用,由于也是一個函數,所以作為一個子作用域,在執行完之后銷毀,避免代碼污染
17 myObj.setI(5); //成功
18 myObj.setI(101); //失敗
19 alert(myObj.getI());
20 alert(myObj.i); //錯誤,沒有該屬性
至此我們簡單的實現了public 訪問權限以及 private 訪問權限 (也就給你想給你的,不給你不想給你的)
在頁面中,我們通常使用 document.cookie 屬性來訪問,對其賦新值就會創建一個新的Cookie,一個Cookie通常具有五個屬性:value (存儲的值), date (UTC格式的時間,代表什么時間過期, domain (域,Cookie的所有者), Path (子目錄).
而在平常的開發中,如果僅僅使用 document.cookie 屬性進行訪問,會很麻煩,因為只能向其賦值字符串,并且在讀取后還要進行字符串切割,才能獲取指定變量名稱的值.document.cookie 讀取時,返回的是所有賦值的值,而不包括過期時間,域之類的信息,只能再次獨設置.