立即執行函數
立即執行函數:函數在定義后立即被執行,有特定的書寫模式。例如:
(function () { alert('watch out!'); }());
或:
(function () { alert('watch out!'); })();
這種模式本質上就是函數表達式(命名的或者匿名的),在創建后立即執行;立即執行函數並不是標准的叫法,是自我理解的叫法。
下面這種寫法是錯誤的:(即將最外層的左右原括號去掉。)
function () { alert('watch out!'); }();
//函數聲明形式,是一個語句。 //報錯:Uncaught SyntaxError: Unexpected token (
var result = function(){
alert('watch out!');
}();
//函數表達式形式,是一個表達式
//不報錯
原因:在一個表達式后面加上括號(),該表達式會立即執行,但是在一個語句后面加上括號(),是完全不一樣的意思,他的只是分組操作符。
要解決上述問題,非常簡單,我們只需要用大括弧將代碼的代碼全部括住就行了,因為JavaScript里括弧()里面不能包含語句,所以在這一點上,解析器在解析function關鍵字的時候,會將相應的代碼解析成function表達式,而不是function聲明。
所以立即執行函數需要有一個()!!!!
考慮一下下面這種常見的場景:
1、你的代碼在頁面代碼加載完成之后,不得不執行一些設置工作,比如附加時間處理器,創建對象等等,
2、所有的這些工作只需要執行一次,所以沒有理由創建一個可復用的命名的函數,
3、但這些代碼也需要一些臨時的變量,但初始化過程結束后,就再也不會被用到了,所以將這些變量作為全局變量不是個好主意,所以我們需要立即執行函數——去將我們所有的代碼包裹在它的局部作用域中,不會讓任何變量泄露成全局變量;
(function() { var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], today = new Date(), msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate(); alert(msg); } ()); // "Today is Fri, 13"
如果代碼沒有被包裹在立即執行函數中,那么局部變量days,today和msg都將成為全局變量,初始化代碼的遺留產物。
立即執行函數的參數
傳遞參數方式如下:
(function(who, when) { console.log("I met " + who + " on " + when); } ("Joe Black", new Date()));
通常,全局變量被作為一個參數傳遞給立即執行參數,這樣它在函數內部不使用window也可以被訪問到:這種方式可以讓代碼在環境(除了瀏覽器)中更加通用:
(function (global) { // access the global object via `global` }(this));
立即執行函數的返回值
就像其它任何函數一樣,一個立即執行函數也能返回值並且可以復制給其它變量:
var result = (function () { return 2 + 2; }());
除了基本類型值,立即執行函數也能返回任何類型的值,包括其它的函數;
那么,你可以利用立即執行函數的作用域為返回的內部函數私下里存儲一些數據。
在接下來的例子中,立即執行函數的返回值是一個函數——被賦值給了變量getResult,這個函數簡單的返回了res的值,這個值事先被計算並被儲存在立即執行函數的閉包中:
var getResult = (function() { var res = 2 + 2; return function() { return res; }; } ());
立即執行函數也可以用來定義對象的屬性;
假如,你需要定義一個很可能在對象生命周期中都不會改變的屬性,但在你定義之前,你需要做一下工作去計算出正確的值;
你可以使用立即執行函數去封裝這些工作,並且立即執行函數的返回值將會成為屬性的值,下面的代碼:
var o = { message: (function() { var who = "me", what = "call"; return what + " " + who; } ()), getMsg: function() { return this.message; } }; // usage o.getMsg(); // "call me" o.message; // "call me"
在這個例子中,o.message是一個字符串類型的屬性,不是一個函數,但它需要一個函數在腳本被載入時被執行並幫忙定義屬性。
通過這個例子感覺String對象的length屬性就是一個立即執行函數算出來的。