本篇主要體驗JavaScript函式的宣告、函式引數以及函式閉包。
□ 函式的宣告
※ 宣告全域性函式
通常這樣宣告函式:
function doSth() {alert("可以在任何時候呼叫我");
}
通過這種方式宣告的函式屬於Window物件,可以在任何地方呼叫,即在doSth方法的之前和之後都可以呼叫。
可以在doSth方法之前呼叫:
doSth();function doSth() {alert("可以在任何時候呼叫我");
}
可以在doSth方法之後呼叫:
function doSth() {alert("可以在任何時候呼叫我");
}doSth();
※ 把函式賦值給變數
var doSomething = function() {alert("只能在宣告我之後再呼叫");
};
不可以在doSomething方法之前呼叫:
doSomething();var doSomething = function() {alert("只能在宣告我之後再呼叫");
};
以上,報"undefined funciton ..."錯。
可以在doSomething方法之後呼叫:
var doSomething = function() {alert("只能在宣告我之後再呼叫");
};doSomething();
□ 函式引數
※ 即使宣告的函式沒有引數,也可以在呼叫時傳入引數
doSth("你好");
function doSth() {alert(arguments[0]);}
輸出結果:你好
※ arguments.callee屬性表示函式引用
doSth("你好");
function doSth() {alert(arguments.callee);}
以上,在函式內部使用arguments.callee屬性表示的是函式本身。
※ arguments.callee()方法遞迴呼叫函式
輸出結果:不斷顯示"你好"doSth();function doSth() {alert("你好");
arguments.callee();}
□ 函式閉包
※ 閉包的形成
先看下面程式碼:
function doSth(val) {return function() {
alert(val);};}var fn = doSth("hello");
fn();
輸出結果:hello
在doSth方法內部返回一個匿名函式,通過fn()執行匿名函式,把doSth方法的引數變數val列印了出來。在這裡,doSth方法內部的匿名函式被稱作"閉包"。換句話說,我們在記憶體上建立了一個匿名物件。
※ 閉包的釋放
如果在呼叫fn方法之後,通過fn=null,把fn設定為null,首先匿名函式所佔記憶體被釋放,接著,由於變數val不再被引用,val所佔記憶體被釋放,最後釋放doSth所佔記憶體。
※ 過多的"閉包"會增加記憶體開銷
function doSth(val) {return function() {
alert(val);};}var fn = doSth("hello");
var fn2 = doSth("hello2");
fn();fn2();fn();
輸出結果:依次顯示hello, hello2, hello
無論是呼叫fn方法,還是fn2方法,都會在記憶體上建立匿名物件,消耗更多的記憶體。
※ 使用"閉包"建立module
舉例:宣告一個函式用來建立唯一的ID
var i = 0;function CreateUniqueName() {var name = "name" + i;
i = i + 1;return name;
}var name1 = CreateUniqueName();var name2 = CreateUniqueName();alert(name1 + " " + name2);
輸出結果:name0 name1
以上存在幾個問題:
1、建立的函式不是全域性的,只能在當前頁使用
2、變數i和方法CreateUnqiueName都是全域性的,這可能會造成與第三方程式碼的名稱衝突
所以,我們應該把以上的邏輯寫成全域性,並做成一個module,並自定義名稱。
var myUtilty = (function() {var i = 0;return {
CreateUniqueName: function() {var name = "name" + i;
i = i + 1;return name;
}};}());var name1 = myUtilty.CreateUniqueName();var name2 = myUtilty.CreateUniqueName();alert(name1 + " " + name2);
○ (function(){}());被稱作是匿名、自觸發函式,返回一個json物件,並且只執行一次
○ 正因為匿名、自觸發函式只被執行一次,所有全域性只有一個myUtitly物件,不會過多消耗記憶體
○ json物件的鍵CreateUniqueName對應一個匿名方法
○ 匿名、自觸發函式可以被看作是全域性的、唯一的"閉包"
“JavaScript進階系列”包括:
JavaScript進階系列01,函式的宣告,函式引數,函式閉包
JavaScript進階系列02,函式作為引數以及在陣列中的應用
JavaScript進階系列03,通過硬編碼、工廠模式、建構函式建立JavaScript物件
JavaScript進階系列04,函式引數個數不確定情況下的解決方案
JavaScript進階系列05,事件的執行時機, 使用addEventListener為元素同時註冊多個事件,事件引數
JavaScript進階系列06,事件委託
JavaScript進階系列07,滑鼠事件