js--函式--IIFE(立即呼叫函式)
阿新 • • 發佈:2019-01-03
1.立即呼叫的函式表示式Immediately-Invoked Function Expression (IIFE)
函式的正常呼叫
函式function foo(){}或者var foo = function(){},呼叫時,你都需要在後面加上一對圓括號,像這樣foo()。
立即呼叫的函式表示式
立即呼叫的函式表示式如果沒有引用的話(沒有賦值給變數),是在程式碼執行階段這個的function就會被建立,並且立即執行,然後自動銷燬。(因為是函式表示式,不在VO中)
//立即呼叫的幾種形式
var foo = function(){}();
//這兩種模式都可以被用來立即呼叫一個函式表示式,利用函式的執行來創造私有變數
(function(){/* code */}());//Crockford recommends this one,括號內的表示式代表函式立即呼叫表示式
(function(){/* code */})();//But this one works just as well,括號內的表示式代表函式表示式
//下面一個立即執行的函式,周圍的括號不是必須的,因為函式已經處在表示式的位置
var foo = {
bar: function (x) {
return x % 2 != 0 ? 'yes' : 'no';
}(1)
};
alert(foo.bar); // 'yes'--foo.bar是一個字串而不是一個函式,這裡的函式僅僅用來根據條件引數初始化這個屬性——它建立後並立即呼叫
function (){}();和function foo(){ }();–都不是立即呼叫的函式表示式,且都會報錯
原因:因為圓括號放在一個函式表示式後面指明瞭這是一個被呼叫的函式;但是有關鍵字function,直譯器會將它看做是函式宣告,若在一個聲明後面則意味著只是一個分組操作符。
比如:
alert(foo); // 函式
function foo(){
alert(x);
}(1);
foo(10); // 這才是一個真正的函式呼叫,結果是10
// 1只是分組操作符,不是函式呼叫,其實相當於下邊這段程式碼
// 下面的宣告的時候產生了2個物件:一個函式宣告,一個帶有1的分組操作符
function foo(){
alert(x);
}
// 一份分組操作符,包含一個表示式1
(1);
解決:將函式宣告包裹在圓括號裡來告訴語法分析器去當成一個函式表示式解析,這樣才對(function foo(){ })()
儲存閉包的狀態
一個立即呼叫的函式表示式可以用來鎖定值並且有效的儲存此時的狀態
閉包:一個函式內的函式可以訪問外部函式作用域的變數
//i沒有被鎖定,相反的,每個連結,當被點選時(迴圈已經被很好的執行完畢),因此會彈出所有元素的總數,因為這是 `i` 此時的真實值。
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + i)
},false);
}
// 而像下面這樣改寫,便可以了,因為在IIFE裡,`i`值被鎖定在了`lockedInIndex`裡。
// 在迴圈結束執行時,儘管`i`值的數值是所有元素的總和,但每一次函式表示式被呼叫時,
// IIFE 裡的 `lockedInIndex` 值都是`i`傳給它的值,所以當連結被點選時,正確的值被彈出。
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
(function(lockedInIndex){
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + lockedInIndex);
},false);
})(i);
}
//你同樣可以像下面這樣使用IIFE,僅僅只用括號包括點選處理函式,並不包含整個`addEventListener`。
//無論用哪種方式,這兩個例子都可以用IIFE將值鎖定,不過我發現前面一個例子更可讀
var elems = document.getElementsByTagName("a");
for(var i = 0,len = elems.length;i < len;i++) {
elems[i].addEventListener('click',(function(lockedInIndex){
return function(e) {
e.preventDefault();
alert('I am link #' + lockedInIndex);
};
}(i),false);
}