- 在JavaScript中,每一個函數(shù)被調(diào)用時贝次,都會創(chuàng)建一個新的執(zhí)行上下文崔兴。因?yàn)樵诤瘮?shù)里定義的變量和函數(shù)是唯一在內(nèi)部被訪問的變量,為而不是在外部被訪問的變量蛔翅,當(dāng)調(diào)用函數(shù)時敲茄, 函數(shù)提供的上下文提供了一個非常簡單的方法創(chuàng)建私有變量。
立即執(zhí)行函數(shù)
- 當(dāng)圓括號出現(xiàn)在匿名函數(shù)的末尾調(diào)用函數(shù)時山析,它會默認(rèn)將函數(shù)當(dāng)成是函數(shù)聲明堰燎。
- 當(dāng)圓括號包裹函數(shù)時, 它會默認(rèn)將函數(shù)作為表達(dá)式去解析笋轨,而不是函數(shù)聲明秆剪。
函數(shù)聲明:
function () {}(); //會報(bào)錯 Function statements require a function name
function f() {}();//不報(bào)錯,也不會執(zhí)行
函數(shù)表達(dá)式:
(function() {})(); //正確執(zhí)行
var foo = function () {
console.log(1111);
}(); //正確執(zhí)行
true && function () {
console.log(1111);
}(); //正確執(zhí)行
如果你并不關(guān)心返回值爵政, 或者讓你的代碼盡可能的易讀仅讽,可以在函數(shù)前面加上一個一元操作符來存儲字節(jié)。
!function(){/* code */}();
~function(){/* code */}();
-function(){/* code */}();
+function(){/* code */}();
new function() {}//直接執(zhí)行
new function() {}(); //僅需傳遞參數(shù)時才需要加括號
關(guān)于括號
- 一些情況下钾挟, 額外的帶著歧義的括號圍繞函數(shù)表達(dá)式是沒有必要的何什,因?yàn)榇藭r括號已經(jīng)將其作為一個表達(dá)式進(jìn)行表達(dá); 正常情況下括號用于調(diào)用函數(shù)表達(dá)式比較常用等龙。
- 例子中括號指明函數(shù)表達(dá)式會被立即調(diào)用, 而且變量將會存儲函數(shù)的結(jié)果伶贰,而不是函數(shù)本身蛛砰。當(dāng)這是一個很長的函數(shù)時可以節(jié)約閱讀代碼的時間,不用滾動或搜索頁面看清函數(shù)是否被調(diào)用黍衙。
- 作為規(guī)則泥畅,當(dāng)寫清楚清晰代碼時,有必要阻止JavaScript拋出的錯誤琅翻, 同樣也有必要阻止其他開發(fā)者對你拋出的錯誤位仁。
保存閉包狀態(tài)
當(dāng)函數(shù)被調(diào)用時柑贞,參數(shù)會被傳遞, 而當(dāng)函數(shù)表達(dá)式被立即調(diào)用時聂抢, 參數(shù)也會被傳遞钧嘶。 但是一個立即調(diào)用的函數(shù)表達(dá)式可以用來鎖定值并且有效的保存此時的狀態(tài), 因?yàn)槿魏味x在一個函數(shù)內(nèi)的函數(shù)都可以使用外面函數(shù)傳遞進(jìn)來的參數(shù)和變量(這種關(guān)系被叫做閉包)琳疏。
舉個lockedIndex的例子:
var elems = document.getElementsByTagName('a');
for(var i = 0;i < elems.length;i++) {
(function(lockedInIndex){
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + lockedInIndex);
},false)
})(i);
}
立即執(zhí)行函數(shù)一個最為著名的優(yōu)勢是有决,就算它沒有命名或者說是匿名,函數(shù)表達(dá)式也可以在沒有使用標(biāo)識符的情況下被立即調(diào)用空盼, 一個閉包也可以在沒有當(dāng)前變量污染的情況下被使用书幕。
自執(zhí)行函數(shù)
1. 遞歸調(diào)用自己
function foo() {foo()};
2. 自執(zhí)行匿名函數(shù) (因?yàn)樗龥]有表示符,必須使用arguments.callee來調(diào)用自己)
(function() {arguments.callee();})
3. 自執(zhí)行匿名函數(shù)揽趾,但是foo標(biāo)識符作為它的引用時台汇,可用foo來調(diào)用
var foo = function() {foo();};
模塊模式
- 返回值用對象代替了函數(shù)
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function(val){
i = val;
},
increment: function(){
return ++i;
}
}
}());
counter.get();//0
counter.set(3);
counter.increment();//4
counter.increment();//5
conuter.i;//undefined (`i` is not a property of the returned object)
i;//ReferenceError: i is not defined (it only exists inside the closure)
- 模塊模式方法不僅相當(dāng)?shù)暮唵螀柡Α7浅I俚拇a篱瞎,你可以有效的利用與方法屬性相關(guān)命名苟呐,在一個對象里,組織全部的模塊化代碼即最小化了全局變量的污染也創(chuàng)造了使用變量奔缠。