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