【JavaScript專題】--- 當即執行函數表達式

一 什麼是當即執行函數表達式

當即執行函數表達式,其實也能夠叫初始化函數表達式,英文名:IIFE,immediately-inovked-function expression。當即執行函數表達式就是在定義的時候就當即執行。html

二 當即執行函數表達式的寫法

1)寫法一express

1 (function (a) {
2   console.log('The result is ' + a);
3 })(5);
4 // The result is 5

2)寫法二segmentfault

1 (function (a) {
2   console.log('The result is ' + a);
3 }(5));
4 // The result is 5

三 當即執行函數表達式的特色

1)做用域隔離,避免污染全局的命名空間數組

經過定義一個匿名函數,建立了一個新的函數做用域,至關於建立了一個「私有」的命名空間,該命名空間的變量和方法,不會破壞污染全局的命名空間。若是想傳給外部變量或者方法,經過給window上添加對應屬性便可。瀏覽器

例如:Jquery插件就是將window傳入,而後給window上添加了$屬性。閉包

2)執行完當即銷燬ide

執行完後,內部的局部變量和整個函數會被銷燬釋放掉。函數

1 (function add(a, b) {
2   console.log('The result is ' + (a + b));
3   return a + b;
4 }(5, 3));
5 
6 add(4, 6);
7 
8 // The result is 8
9 // Uncaught ReferenceError: add is not defined

3)當即執行函數表達式不須要帶函數名this

若是帶了函數名,則被自動忽略。spa

四 當即執行函數表達式的錯誤寫法

下邊會針對一些當即執行函數表達式的錯誤寫法,深刻說明其緣由。

要很好的理解下邊錯誤寫法的緣由,首先要了解:JavaScript中函數的定義方法;JavaScript中表達式。

1)錯誤寫法一

下邊的錯誤寫法的緣由:瀏覽器解析器遇到function開頭的語句,認爲這是一個函數定義,但發現該函數沒有函數名,致使報錯。

1 function () {
2   console.log('The result is 1');
3 }();
4 
5 // Uncaught SyntaxError: Unexpected token (

說明:爲何給上邊示例代碼添加一個圓括號,就能夠執行而且不報錯了?

這是由於添加圓括號後,就變成表達式。

咱們都知道定義函數有兩種方式:

1 // 函數聲明:使用function聲明函數,並指定函數名
2 function add() {
3   console.log('The result is 1');
4 }
5 
6 // 函數表達式:使用function聲明函數,但未指定函數名,將匿名函數賦予一個變量
7 var add = function() {
8   console.log('The result is 1');
9 };

所以當即執行函數表達式,就相似於給函數表達式方式定義的函數,只是在函數定義完添加了圓括號讓該函數當即執行了。

根本的緣由仍是將一個函數定義,變成了一個表達式。這也是爲何叫當即執行函數表達式的緣由。

讓一個匿名函數變成一個表達式的方法不少:

1 !function(){}();
2 +function(){}();
3 -function(){}();
4 ~function(){}();
5 new function(){ /* code */ }
6 new function(){ /* code */ }() // 只有傳遞參數時,才須要最後那個圓括號。
7 ……

2)錯誤寫法二

1 function add() {
2   console.log('The result is ' + a);
3 }();
4 
5 // Uncaught SyntaxError: Unexpected token )

上邊代碼會被瀏覽器解析爲以下樣子:

1 function add() {
2   console.log('The result is ' + a);
3 };
4 ();

第一個分號前是一個完整的函數定義,沒有問題;而第二個分號前的(),出現了語法報錯。

注意:當咱們給後邊的那個圓括號中添加一個表達式後,就不會報錯了。但注意add函數依然不會執行。

 1 function add() {
 2   console.log('The result is 1');
 3 }(2);
 4 
 5 
 6 // 上邊等價於下邊代碼:一部分是函數聲明,一部分是執行表達式。所以函數不會執行。
 7 function add() {
 8   console.log('The result is 1');
 9 };
10 (2);

3)錯誤寫法三

當有多個當即執行函數表達式時,必定要帶分號:

1 (function () {
2   console.log('this is IIFE 1');
3 }())
4 (function () {
5   console.log('this is IIFE 1');
6 }())
7 
8 // VM80:4 Uncaught TypeError: (intermediate value)(...) is not a function

說明:不帶分號會致使JavaScript執行器認爲後邊括號內容是前邊括號內容的參數,而前邊括號最終執行結果並非一個函數。而下邊代碼就不會報錯:

 1 (function () {
 2   console.log('this is IIFE 1');
 3   return function(a) {
 4     console.log('this is IIFE 1 return');
 5   }
 6 }())
 7 (function () {
 8   console.log('this is IIFE 2');
 9 }())
10 
11 // this is IIFE 1
12 // this is IIFE 2
13 // this is IIFE 1 return

 五 當即執行函數組成的閉包保存狀態

 1 // 這個代碼是錯誤的,由於變量i歷來就沒背locked住
 2 // 相反,當循環執行之後,咱們在點擊的時候i纔得到數值
 3 // 由於這個時候i操真正得到值
 4 // 因此說不管點擊那個鏈接,最終顯示的都是I am link #10(若是有10個a元素的話)
 5 
 6 var elems = document.getElementsByTagName('a');
 7 
 8 for (var i = 0; i < elems.length; i++) {
 9 
10     elems[i].addEventListener('click', function (e) {
11         e.preventDefault();
12         alert('I am link #' + i);
13     }, 'false');
14 
15 }
16 
17 // 這個是能夠用的,由於他在自執行函數表達式閉包內部
18 // i的值做爲locked的索引存在,在循環執行結束之後,儘管最後i的值變成了a元素總數(例如10)
19 // 但閉包內部的lockedInIndex值是沒有改變,由於他已經執行完畢了
20 // 因此當點擊鏈接的時候,結果是正確的
21 
22 var elems = document.getElementsByTagName('a');
23 
24 for (var i = 0; i < elems.length; i++) {
25 
26     (function (lockedInIndex) {
27 
28         elems[i].addEventListener('click', function (e) {
29             e.preventDefault();
30             alert('I am link #' + lockedInIndex);
31         }, 'false');
32 
33     })(i);
34 
35 }
36 
37 // 你也能夠像下面這樣應用,在處理函數那裏使用自執行函數表達式
38 // 而不是在addEventListener外部
39 // 可是相對來講,上面的代碼更具可讀性
40 
41 var elems = document.getElementsByTagName('a');
42 
43 for (var i = 0; i < elems.length; i++) {
44 
45     elems[i].addEventListener('click', (function (lockedInIndex) {
46         return function (e) {
47             e.preventDefault();
48             alert('I am link #' + lockedInIndex);
49         };
50     })(i), 'false');
51 
52 }

 

六 參考資料&內容來源

博客園:https://www.cnblogs.com/tomxu/archive/2011/12/31/2289423.html

SF:http://www.javashuo.com/article/p-pldiqnob-cr.html

百度:https://baijiahao.baidu.com/s?id=1627496475450434415&wfr=spider&for=pc

博客園:http://www.javashuo.com/article/p-pjmyzoku-dk.html

相關文章
相關標籤/搜索