匿名函數就是沒有名字的函數,有時候也稱為拉姆達(lambda)函數。
function functionName(){};
這是一個函式宣告
在代碼執行以前被載入到範圍中
var functionName = function(){};
這是一個函數運算式
在代碼執行到那一行時才會有定義
7.1 遞迴
arguments.callee是一個指向正在執行的函數的指標,可以實現函數的遞迴調用
function factorial(num){
if(num <= 1){
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); // output 24
7.2 閉包
閉包是指有權訪問另一個函數範圍中的變數的函數。建立閉包的常見方式,就是在一個函數內部建立另一個函數。
function fn(propertyName){
return function(object1){
var v1 = object1[propertyName]; //訪問了外部變數propertyName變數
}
}
由於閉包會攜帶包含它的函數的範圍,因此會比其他函數佔用更多的記憶體,過度使用閉包可能會導致記憶體佔用過多。所以建議只是在絕對必要時再考慮使用閉包。
7.2.1 閉包與變數
function createFunctions(){
var result = [];
for(var i=0; i<10; i++){
result[i] = function(num){
return function(){
return num;
}
}(i);
}
}
var funcs = createFunctions();
for(var i=0; i<funcs.length; i++){
document.write(funcs[i] + ‘<br />’); //output 0,1,2,3…9
}
7.2.2 this對象
this對象是在運行時基於函數的執行環境綁定的:在全域函數中,this等於window,而當函數被作為某個對象的方法調用時,this等於那個對象。不過,匿名函數的執行環境具有全域性,因此對象通常指向window.
7.2.3 記憶體流失
如果閉包的範圍中儲存著一個HTML元素,那麼就意味著該元素無法被銷毀。
function assignHandler(){
var element = document.getElementById(‘someElement’);
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null; //變數設定為null,才能解除對DOM對象的引用,順利減少引用數,確保正常回收其佔用的記憶體
}
7.3 模仿塊級範圍
匿名函數可以用來模仿塊級範圍:
(function(){
//這裡是塊級範圍
})();
將函式宣告包含在一對圓括弧中,表示它實際上是一個函數運算式,而緊隨其後的另一對圓括弧會立即調用這個函數。
相當於:
var someFunction = function(){};
someFunction();
function(){}();
這一段會導致語法錯誤,因為JavaScript將function關鍵字當作一個函式宣告的開始,而函式宣告後面不能跟圓括弧。然而,函數運算式的後面可以跟圓括弧。要將函式宣告轉換成函數運算式,只要加上一對括弧即可。
7.4 私人變數
任何在函數中定義的變數,都可以認為是私人變數。因為在函數外部不能訪問這些變數。
把有權訪問私人變數和私人函數的公有方法叫特權方法。
function MyObject(){
//私人變數
var privateVariable = 10;
function privateFunction(){
return false;
}
//特權方法
this.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
}
7.4.1 靜態私人變數
(function(){
var privateVariable = 10;
function privateFunction(){
}
Myobject = function(){
}
//公有/特權方法
Myobject.prototype.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
})()
這個模式建立了一個私人範圍,並在其中封裝了一個建構函式及相應的方法。
7.4.2 模組模式
單例建立私人變數和特權方法。所謂單例就是只有一個執行個體的對象。簡單的文法如下:
var singleton = {
name: value,
method: function(){
//這裡是方法
}
}
還可以添加私人變數和特權方法
var singleton = function(){
//私人變數和私人函數
var privateVariable = 10;
function privateFunction(){}
//特權/公有方法和屬性
return {
publicProperty: true,
publicMethod: function(){
privateVariable++;
return privateFunction();
}
}
}
這個模式返回了一個匿名函數,在函數內部,定義私人變數和函數,然後將一個對象字面量作為函數的值返回。返回的對象字面量中只包含可以公開的屬性和方法。
7.4.3 增強模組模式
var singleton = function(){
//私人變數和私人函數
var privateVariable = 10;
function privateFunction(){
return false;
}
//建立對象
var object = new CustomType();
//添加特權/僅有屬性和方法
object.publicProperty = true;
object.publicMethod = function(){
privateVariable++;
return privateFunction();
};
return object;
}