摘要:把這兩個因素結(jié)合起來,就能通過把變量包裹在匿名函數(shù)中而對其加以保護(hù)。執(zhí)行完后雖然已經(jīng)變成數(shù)組的長度,但是匿名函數(shù)每次立即執(zhí)行的時候傳入的參數(shù)是相應(yīng)的四函數(shù)定義內(nèi)調(diào)用本身在中被廢棄了。
一 閉包和作用域
閉包是一個受到保護(hù)的變量空間,由內(nèi)嵌函數(shù)生成。JavaScript具有函數(shù)級的作用域。這意外著定義在函數(shù)內(nèi)部的變量在函數(shù)外部不能被訪問。JavaScript的作用域又是詞法性質(zhì)的。這意味著函數(shù)運(yùn)行在定義它的作用域中,而不是在調(diào)用它的作用域中。把這兩個因素結(jié)合起來,就能通過把變量包裹在匿名函數(shù)中而對其加以保護(hù)。(引自《JavaScript設(shè)計模式》)
var i = 100; function makeCounter() { var i = 0; // makeCounter的私有變量 return function() { console.log(++i); } //該函數(shù)運(yùn)行的環(huán)境是makeCounter的作用域 } var counter = makeCounter(); // counter即makeCounter的內(nèi)嵌函數(shù),運(yùn)行時獲取的i來源于makeCounter作用域中的i counter(); // 輸出: 1 而非 101 –>因?yàn)閙akeCounter返回的內(nèi)嵌函數(shù)能獲取i,所以也稱為makeCounter的特權(quán)函數(shù)。 counter(); // 輸出: 2 i; // 輸出: 100 –>說明makeCounter內(nèi)的i不能被調(diào)用
二 () 調(diào)用函數(shù)
(1)function foo() {} 和 var foo = function() {},foo都是這里function(){}的引用,調(diào)用時只需要直接foo()。但如果直接將()放在function(){}后面則會觸發(fā)語法錯誤。
function() {..}() // SyntaxError: Unexpected token(
原因:當(dāng)解析器遇到function關(guān)鍵字時,默認(rèn)將其視為一個函數(shù)聲明(function declaration),而不是一個函數(shù)表達(dá)式(function expression)。如果不顯式告訴解析器將其視為一個函數(shù)表達(dá)式,則會視其為一個函數(shù)聲明缺少名字的語法錯誤。
(2)針對上面語法錯誤,給函數(shù)加個名稱并加()執(zhí)行,會觸發(fā)另外一個語法錯誤:
function foo() {….} () ; // SyntaxError: Unexpected token )
原因:()放在表達(dá)式后面表示這個表達(dá)式是個函數(shù)并將要被調(diào)用,而()放在statement(函數(shù)聲明也是個statement)后面則是用來與前一個statement分隔,僅僅是一個分組運(yùn)算符(用在控制運(yùn)算優(yōu)先級的,即: 1 + 2 * ( 3 + 4 )這里括號的作用 )
修正:()作為分組運(yùn)算符時,需要包含一個表達(dá)式,所以簡單加個表達(dá)式 (1)。
function foo() {…}(1) ; //不會報錯了,這樣的寫法其實(shí)等同于下面 function foo() {…} // 所以foo在這里并沒有被調(diào)用,而僅僅是個聲明而已。 (1)
(3)上面的修正只是解決了語法錯誤,但實(shí)際上并沒有達(dá)到我們的期望:讓函數(shù)立即執(zhí)行。最常用的方法是將其包在()內(nèi)。因?yàn)樵贘avaScript中,()只能包含表達(dá)式而不能是語句statement。
(function() {..}()) 或者 (function() {..})()
(4)其他方法:原理都是令解析器認(rèn)識到()前是一個表達(dá)式
var x = function() { return 1; }(); true && function() { .. } (); 0, function() {..} () ! function() {..} () ~ function() {..} () + function() {..} () – function() {..} ()
三 利用閉包保存狀態(tài)
(1)下面例子給元素添加事件監(jiān)聽,結(jié)果每個a點(diǎn)擊后輸出的都是elmes數(shù)組的長度。
原因:for執(zhí)行后的每個elems的點(diǎn)擊事件函數(shù)中綁定的是 j ,當(dāng)點(diǎn)擊時輸出的 j 確確實(shí)實(shí)就是 j 在for運(yùn)行之后的值。
var elems = document.getElementsByTagName(‘a(chǎn)’); for (var j = 0; j < elems.length; j++) { elems[j].addEventListener(‘click’, function(e) { e.preventDefault(); console.log (j); }, false); }
(2)下面例子利用立執(zhí)行函數(shù),將 j 鎖定。
for執(zhí)行完后 j 雖然已經(jīng)變成elems數(shù)組的長度,但是匿名函數(shù)每次立即執(zhí)行的時候傳入的參數(shù)是相應(yīng)的 j
var elems = document.getElementsByTagName(‘a(chǎn)’); for (var j = 0; j < elems.length; j++) { (function( lockedIndex ) { elems[j].addEventListener(‘click’, function(e) { e.preventDefault(); console.log(lockedIndex); }, false); })(j); }
四 函數(shù)定義內(nèi)調(diào)用本身
function foo() { foo(); } var foo = function() { arguments.callee(); } // arguments.callee 在ECMAScript5中被廢棄了。
五 參考
immediately-invoked-function-expression
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86042.html
摘要:前言大家學(xué)的時候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來想想說一下自執(zhí)行。其實(shí),前面兩個例子里的變量,也可以換成,因?yàn)楹屯饷娴牟辉谝粋€作用于,所以不會出現(xiàn)問題,這也是匿名函數(shù)閉包的威力。 前言 大家學(xué)JavaScript的時候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來想想說一下自執(zhí)行。 在詳細(xì)了解這個之前,我們來談了解一下自執(zhí)行這個叫法,本文對這個功能的叫法也不一定完全對...
摘要:作用域和閉包以及自執(zhí)行函數(shù)作用域作用域分為種全局作用域全局作用域就是在的任何位置都能訪問過函數(shù)作用域只能在函數(shù)里面調(diào)用的稱之為函數(shù)作用域閉包嵌套在函數(shù)里面的函數(shù)及周邊的變量叫閉包閉包存在的問題是周邊變量不會被釋放,常駐內(nèi)存中閉包的缺點(diǎn)消耗內(nèi) 作用域和閉包以及自執(zhí)行函數(shù) 作用域 作用域分為2種 1、全局作用域 全局作用域就是在js的任何位置都能訪問過 2、函數(shù)作用域 只能在函數(shù)里面調(diào)用的...
摘要:打開源碼,首先你會看到這樣的代碼結(jié)構(gòu)這是一個自調(diào)用匿名函數(shù)。模式,是自執(zhí)行函數(shù)的高級模式,可以非常方便的在各個匿名閉包中以全局對象調(diào)用閉包函數(shù)。 打開jQuery源碼,首先你會看到這樣的代碼結(jié)構(gòu): (function(window,undefined ){ // })(); 這是一個自調(diào)用匿名函數(shù)。什么東東呢?在第一個括號內(nèi),創(chuàng)建一個匿名函數(shù);第二個括號,立即執(zhí)行 為什么要創(chuàng)建這樣一個...
摘要:但是到底是如何找到對應(yīng)的函數(shù)的呢今天,我們來一起尋找答案函數(shù)分類首先,我們先回顧一下的函數(shù)分類,函數(shù)包含用戶自定義函數(shù)內(nèi)部函數(shù)匿名函數(shù)等多種類型。用戶自定義函數(shù)和內(nèi)部函數(shù)編譯完成后會將函數(shù)名注冊到全局函數(shù)列表中。 對于PHPer而言,我們通常會把常用的功能封裝成一個函數(shù)來進(jìn)行復(fù)用,以提升開發(fā)效率。但是php到底是如何找到對應(yīng)的函數(shù)的呢?今天,我們來一起尋找答案~ 函數(shù)分類 首先,我們先...
摘要:組件化開發(fā)小程序在未出現(xiàn)組件之前,要重用的話,只能簡單復(fù)制粗暴黏貼組件化開發(fā)的優(yōu)勢可復(fù)用代碼分離,可維護(hù)更重要定義組件先創(chuàng)建文件夾用于存放組件,然后再創(chuàng)建組件文件夾注意組件的文件名并不是組件名,而頁面文件名是頁面名,組件名是引用時才確定的引 組件化開發(fā) 小程序在未出現(xiàn)組件之前,要重用的話,只能簡單(復(fù)制)粗暴(黏貼) 組件化開發(fā)的優(yōu)勢: 1、可復(fù)用(wxml/wxss/js) 2、代...
摘要:為了更加方便的處理異步操作問題,現(xiàn)在最新的前端框架生態(tài)都開始用上了和,有的甚至已經(jīng)開始使用最新的語法了,這兩樣都是基于自動執(zhí)行的原理。這里就簡單理解下自執(zhí)行及語法原理一函數(shù)函數(shù)指的是能將執(zhí)行結(jié)果傳入回調(diào)函數(shù),并將該回調(diào)函數(shù)返回的函數(shù)。 為了更加方便的處理異步操作問題,現(xiàn)在最新的前端框架生態(tài)都開始用上了Generator和yield,有的甚至已經(jīng)開始使用最新的async、await語法了...
閱讀 3395·2021-10-13 09:40
閱讀 2619·2021-10-08 10:17
閱讀 4030·2021-09-28 09:45
閱讀 960·2021-09-28 09:35
閱讀 1846·2019-08-30 10:51
閱讀 2931·2019-08-26 12:11
閱讀 1677·2019-08-26 10:41
閱讀 3120·2019-08-23 17:10