在前端面試中面試官基本都會問到什麼是匿名函數、什麼是閉包函數。前端
本文就先來講一下什麼是匿名函數。面試
匿名函數顧名思義就是沒有名字的函數,一般咱們所寫的函數都是這樣的:編程
1 function do(){ 2 // 執行代碼 3 }; 4 5 // 調用 6 do();
這種寫法是定義了一個名爲do的函數,並經過函數名稱進行調用。瀏覽器
那若是沒有名字是什麼樣子的啊?閉包
1 function () { 2 // 執行代碼 3 };
這種寫法在編譯的時候會報錯:編程語言
Uncaught SyntaxError: Unexpected token (函數
這是爲何呢?原來時由於瀏覽器在進行語法分析的時候發現這個函數根本無法執行。工具
那要爲何還要匿名函數呢?在編程語言中若是又個編碼方式那這種編碼方式確定是能正常運行的,那該如何讓匿名函數跑起來呢?再看下面的例子:編碼
var do = function () { // 執行代碼 } do();
這種函數你們確定都知道,其實這種寫法就是將匿名函數複製爲變量do,再經過變量名執行函數。spa
(function(){ // 執行代碼
console.log("打印成功"); })();
上面代碼是什麼意思呢?
能夠先把上面的代碼分幾個部分:
第一部分是括號裏面的匿名函數,第二部分是加上括號的匿名函數,第三部分帶上最後面執行用的括號。
匿名函數在括號內部能夠當作是將匿名函數當成是一個變量,再經過括號進行執行。
(function () { // 執行代碼 })(); // 至關於 var do = function() { // 執行代碼 }; do();
其實向上面這種匿名函數的寫法在不少地方都有用到,這種又叫自執行函數,像JQuery 等一些工具包都會用這種寫法,自執行函數有哪些優勢呢?
1 // 定義一個全局變量a 2 var a = 1; 3 4 (function() { 5 // 在自執行函數中也建立一個變量a 6 var a = 2; 7 console.log(a); // 2 8 })(); 9 10 console.log(a); // 1
能夠看到在自執行函數中打印出來的是2,而在自執行函數中打印出來的是1;
這是爲何?
由於在程序中有個名稱叫作做用域,全局環境的做用域叫作全局做用域,函數中的做用域叫作函數做用域,而做用域是分層的,內部做用域中能夠訪問外部做用域中的變量,而外部做用域中卻不能夠訪問內部做用域中的變量。
在內部做用域中訪問變量會先在本身所在做用域中查找,若是找不到再在上一層做用域中進行查找,再找不到還會再往上查找,一直到找到全局做用域。這種一層一層的關係像鏈條同樣因此被叫作做用域鏈。
再看上面代碼:在自執行函數中console.log 函數訪問了a變量,首先在本身所在的做用域中查找,找到了a變量,故輸出了a的值2;全局環境中的console.log 函數也訪問了a變量,因爲外部做用域不能訪問內部做用域,因此全局環境中訪問的a變量只能在全局函環境中進行查找,因此輸出了a的值1;
總結:自執行函數的優勢是爲了保證自執行函數中的變量不會受到其餘環境的污染。