標籤:span ted cee lan target 構造 執行函數 函數運算式 set
常用的兩種寫法:
(function(){ /* code */ }()); (推薦寫法)
(function(){ /* code */ })();
Q:為什麼這樣寫,函數就嗯那個立即執行?
A:因為在javascript裡,括弧內部不能包含語句,當解析器對代碼進行解釋的時候,先碰到了(),然後碰到function關鍵字就會自動將()裡面的代碼識別為函數運算式而不是函式宣告。
eg:如下代碼就會報錯。
function(){ /* code */ }(); // SyntaxError: Unexpected token (
why?!因為在javascript代碼解釋時,當遇到function關鍵字時,會預設把它當做是一個函式宣告,而不是函數運算式,如果沒有把它顯視地表達成函數運算式,就報錯了,因為函式宣告需要一個函數名,而上面的代碼中函數沒有函數名。(以上代碼,也正是在執行到第一個左括弧(時報錯,因為(前理論上是應該有個函數名的。)
立即執行函數與閉包的曖昧關係:
像普通的函數傳參一樣,立即執行函數也能傳參數。如果在函數內部再定義一個函數,而裡面的那個函數能引用外部的變數和參數(閉包),利用這一點,我們能使用立即執行函數鎖住變數儲存狀態。通過以下兩段代碼可更好理解:
<body> <div>0</div> <div>1</div> <div>2</div> <div>3</div></body><script> var nodes = document.getElementsByTagName("div"); for (var i = 0; i < nodes.length; i++) { nodes[i].onclick = function () { console.log(i); } }</script>
//一次點擊div,輸出的結果卻不是0~3,輸出的都是3。這是為什麼呢?!
因為div節點的onclick事件是被非同步觸發的,當事件被觸發的時候,for循化早已結束,此時變數 i 已經是3,所以div的onclick事件函數終順著範圍從內到外尋找變數變數i時,查到的值總是3。那樣怎麼辦才能得到想要的呢?
<body> <div>0</div> <div>1</div> <div>2</div> <div>3</div></body><script> var nodes = document.getElementsByTagName("div"); for (var i = 0; i < nodes.length; i++) { (function (i) { nodes[i].onclick = function () { console.log(i); } })(i) }</script>
//此時控制台就會輸出對應的值了,為什麼呢?
因為在立即執行函數內部 i 的值被鎖在記憶體中,儘管for迴圈結束後 i 的值已經改變,但是立即執行函數內部 i 的值並不會改變。
立即執行函數在模組化中的用處:
用立即執行函數處理模組化可以減少全域變數造成的空間汙染,構造更多的私人變數。
// 建立一個立即執行的匿名函數// 該函數返回一個對象,包含你要暴露的屬性// 如下代碼如果不使用立即執行函數,就會多一個屬性i// 如果有了屬性i,我們就能調用counter.i改變i的值 var counter = (function(){ var i = 0; return { get: function(){ return i; }, set: function( val ){ i = val; }, increment: function() { return ++i; } };})();
// counter其實是一個對象
counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5
counter.i; // undefined i並不是counter的屬性
i; // ReferenceError: i is not defined (函數內部的是局部變數)
原文:Immediately-Invoked Function Expression (IIFE)
G~G~ Study。
javascript立即執行函數運算式(IIFE)