摘要:第一種方法是上面已經說到的匿名函數表達式,即將匿名函數賦值給一個變量,然后通過變量名去調用。因為函數聲明是不能被執行符號執行的,除非通過函數名調用,只有表達式才能被執行符號執行匿名函數又沒有函數名,另外的辦法就是把它變成表達式。
函數聲明
function funcName(){ }; console.log(funcName); // 打印結果是funcName這個函數體。
聲明一個函數funcName,funcName就是函數名,函數名是函數聲明的必要組成部分,函數其實就是另一個類型的變量,函數名稱相當于變量名,新聲明的函數體會賦值給這個變量名,之后調用該函數的時候都需要通過該變量名進行調用。
函數表達式
// 命名函數表達式 var funcName = function abc() {}; console.log(funcName); // 打印函數體function abc(){} console.log(abc); // 報錯(abc is not defined)
在這個函數表達式中,函數名稱為abc,其實上,這個名稱abc變成了函數內部的一個局部變量,并且指代函數對象本身,在abc函數內部打印abc的打印結果是abc函數體本身。
var funcName = function abc() { console.log(abc); // 打印結果是function abc() {console.log(abc)} };
所以,在全局console.log(abc);肯定會報錯,因為abc是局部變量,全局是拿不到的,這個函數表達式會忽略函數的名稱,調用的時候要通過變量名進行調用——funcName();
// 匿名函數表達式 var funcName = function () {};
匿名函數表達式顧名思義就是沒有名字的函數表達式,一般情況下,我們所說函數表達式就指匿名函數表達式,因為函數表達式會忽略函數的名稱,會變成匿名函數表達式,不如直接寫成匿名函數表達式。
函數表達式與函數聲明不同的是,函數聲明只是聲明了一個函數,在預編譯的時候,函數聲明的聲明提升函數體也提升,所以不管你是在函數聲明之前調用還是在之后調用,都能正常執行。
demo(); // 結果是"a" function demo(){ console.log("a"); }; demo(); // 結果是"a"
而函數表達式在預編譯時,是變量名提升,只有當執行到函數表達式所在行的代碼時,才將函數體賦值給該變量,所以在函數表達式之前調用該函數會報錯,只能在之后調用。
demo(); // 報錯 var demo = function (){ console.log("a") }; demo(); // 結果是"a"
匿名函數
匿名函數顧名思義就是沒有名字的函數。(匿名函數有多種用途,寫在文末)
function () {};
既然是沒有名字的函數,那我們要怎樣找到它調用它呢?這里要提到兩種方法。
第一種方法是上面已經說到的匿名函數表達式,即將匿名函數賦值給一個變量,然后通過變量名去調用。
var abc = function (){}; abc();
第二種方法就是接下來要說的立即執行函數。
立即執行函數
立即執行函數有兩種寫法:
// 第一種 w3c標準建議使用這一種 (function (){})(); // 第二種 (function(){}());
這里有兩個括號有點疑問,在解釋兩個括號的作用前,我們先明確幾點:
1.只有表達式才能被執行符號執行,函數聲明是不能被執行符號執行的。
2.能被執行符號執行的表達式,這個函數的名字就會被自動忽略(放棄名字)。
3.能被執行符號執行的表達式基本上就是立即執行函數。
因為函數聲明是不能被執行符號執行的,除非通過函數名調用,只有表達式才能被執行符號執行(匿名函數又沒有函數名,另外的辦法就是把它變成表達式)。
function (){ console.log("a"); // 報語法錯誤,因為只有表達式才能被執行符號()執行 }();
(function (){})()
所以此處匿名函數兩邊的括號運算符,作用是把函數轉換為表達式(至于怎樣轉換的,更深層的原理有興趣的童鞋可以研究研究,后續我會進行補充的),后面的括號為執行符號,(function (){})()就相當于匿名函數表達式的執行。
(function (){})()和(function(){}())寫法其實沒多大區別,(function(){}())也是一直等價的表達式,但是w3c標準建議使用第一種。
將函數聲明轉化成表達式的方式有很多,例如把它賦值給一個變量,再例如在函數聲明前放上+運算符,-運算符,!運算符等。
// 把它賦值給一個變量 var demo = function(a){ console.log(a); // 結果為1 }(1) // 使用+運算符 +function(a){ console.log(a); // 結果為1 }(1); // 使用-運算符 -function(a){ console.log(a); // 結果為1 }(1); // 使用!運算符 !function(a){ console.log(a); // 結果為1 }(1);
當表達式被執行,函數的名字就會被放棄,舉兩個栗子:
var demo = function(){}(); console.log(demo); // 結果會報錯,因為函數名被放棄了。 +function demo(){}(); console.log(demo); // 結果會報錯,因為函數名被放棄了。
匿名函數有很多作用,例如將匿名函數賦予一個變量來創建一個函數,例如賦予一個事件則成為事件處理程序,再例如用立即執行函數創建閉包防止污染全局變量等等
// 將匿名函數賦予一個變量來創建一個函數 var demo = function(){}; // 賦予一個事件則成為事件處理程序 $(selector).on("click",function(){}); // 用立即執行函數創建閉包 (function(window, undefined))(window);
本文只是簡單分析以助自己理清思路,有錯誤之處請不吝賜教。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109072.html
摘要:而且,如果你想跳過這里,你可以直接跳到立即調用函數表達式進行閱讀,但是我建議你讀完整篇文章。當圓括號包裹函數時,它會默認將函數作為表達式去解析,而不是函數聲明。什么是呢它使一個被立即調用的函數表達式。一旦命名,函數將不再匿名。 原文:http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iif...
摘要:另外,如果你想跳過這里,你可以直接跳到立即調用函數表達式進行閱讀,但是我建議你讀完整篇文章。當圓括號包裹函數時,它會默認將函數作為表達式去解析,而不是函數聲明。 原文:Immediately-Invoked Function Expression (IIFE) by Ben Alman原譯:立即執行函數 by Murphywuwu改增內容: by blanu 也許你沒有注意到,我是一個...
摘要:前言最近在學前幾天看到兩道題剛開始看懵懵懂懂這幾天通過各種查資料慢慢的理解頓悟了對匿名函數閉包立即執行函數的理解也更深了一點在此分享給大家我的理解與總結希望能幫助大家理解因為這篇文章是我用心總結的查閱了很多的資料所以總結的比較細篇幅較長如果 前言 最近在學JS,前幾天看到兩道題,剛開始看懵懵懂懂,這幾天通過各種查資料,慢慢的理解,頓悟了,對匿名函數,閉包,立即執行函數的理解也更深了一點...
摘要:而閉包的神奇之處正是可以阻止事情的發生。拜所聲明的位置所賜,它擁有涵蓋內部作用域的閉包,使得該作用域能夠一直存活,以供在之后任何時間進行引用。依然持有對該作用域的引用,而這個引用就叫閉包。 引子 先看一個問題,下面兩個代碼片段會輸出什么? // Snippet 1 a = 2; var a; console.log(a); // Snippet 2 console.log(a); v...
摘要:匿名函數的好處在于可以減少局部變量,以免污染現有的運行環境。另外通過,這三個符號運行的匿名函數比運行的匿名函數可以減少一個字符的使用但是我們通常使用加因為其他的操作符可能會帶來其他的影響更多可以參考 js中的立即執行函數 ( function(){…} )()和( function (){…} () )是兩種javascript立即執行函數的常見寫法 問題: 為什么會出現上面的兩種不一...
閱讀 1551·2023-04-26 02:29
閱讀 3015·2021-10-11 10:58
閱讀 2893·2021-10-08 10:16
閱讀 3154·2021-09-24 09:47
閱讀 1562·2019-08-29 16:56
閱讀 2711·2019-08-29 11:03
閱讀 1991·2019-08-26 13:35
閱讀 3167·2019-08-26 13:34