久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      淺談JS函數(shù)及閉包

      每聲明一個(gè)函數(shù)就會(huì)產(chǎn)生一個(gè)作用域。而外面的作用域訪問(wèn)不了里面的作用域(把里面的變量和函數(shù)隱藏起來(lái)),而里面的可以訪問(wèn)到外面的。對(duì)于隱藏變量和函數(shù)是一個(gè)非常有用的技術(shù)。

      淺談JS函數(shù)及閉包

      基于作用域隱藏的方法叫做最小授權(quán)最小暴露原則。

      這個(gè)原則是指在軟件設(shè)計(jì)中,應(yīng)該最小限度的暴露必要內(nèi)容,而將其內(nèi)容都隱藏起來(lái),比如某個(gè)模塊或?qū)ο蟮肁PI設(shè)計(jì)。隱藏變量和函數(shù)可以解決同名標(biāo)識(shí)符的之間的沖突,沖突會(huì)導(dǎo)致變量的意外覆蓋。

      例如:

      var a = 2; function foo(){   var a = 3;   console.log(a); } foo(); console.log(a);

      雖然這種技術(shù)可以解決一些問(wèn)題,但是他并不理想,會(huì)導(dǎo)致一些額外的問(wèn)題,首先必須聲明一個(gè)具名函數(shù)foo(),意味著foo這個(gè)名稱本身“污染”了所在的作用域,其次必須顯式的通過(guò)函數(shù)名foo()調(diào)用這個(gè)函數(shù)才能運(yùn)行其中的代碼。

      如果函數(shù)不需要函數(shù)名,并且能夠自動(dòng)運(yùn)行,這會(huì)更加理想。幸好js提供了同時(shí)解決這兩個(gè)問(wèn)題的方案 — (IIFE) Immediately Invoked Function Expression — 立即執(zhí)行函數(shù)

      var a = 2; (function foo(){     var a = 3;     console.log(a); })() console.log(a);

      首先立即執(zhí)行函數(shù)不會(huì)當(dāng)做函數(shù)聲明處理而當(dāng)做函數(shù)表達(dá)式處理。

      區(qū)分函數(shù)聲明還是函數(shù)表達(dá)式:看function在聲明中是不是第一個(gè)詞,如果是第一個(gè)詞就是函數(shù)聲明否則就是函數(shù)表達(dá)式。而立即執(zhí)行函數(shù)" (function ",不是" function ",所以是函數(shù)表達(dá)式。

      函數(shù)聲明函數(shù)表達(dá)式之間重要的區(qū)別是他們的名稱標(biāo)識(shí)符將會(huì)綁定在何處

      函數(shù)聲明的函名稱數(shù)會(huì)綁定在當(dāng)前作用域內(nèi)。假如在全局作用域創(chuàng)建一個(gè)函數(shù)聲明,就可以在全局作用域訪問(wèn)這個(gè)函數(shù)名稱并執(zhí)行。而函數(shù)表達(dá)式的函數(shù)名稱會(huì)綁定在自身的函數(shù)中,而不是當(dāng)前說(shuō)在作用域中。例如你全局創(chuàng)建一個(gè)函數(shù)表達(dá)式,如果你直接執(zhí)行這個(gè)你創(chuàng)建的函數(shù)表達(dá)式的函數(shù)名就會(huì)報(bào)錯(cuò),因?yàn)楫?dāng)前作用域下沒(méi)有這個(gè)標(biāo)識(shí)符,而你在函數(shù)表達(dá)式里面的作用域里訪問(wèn)這個(gè)函數(shù)名就會(huì)返回這個(gè)函數(shù)的引用。

      作用域閉包,嗯,閉包這兒兩個(gè)字就有點(diǎn)讓人難以理解,(可以想象成一個(gè)包是關(guān)上的,里面隱藏了一些神秘的東西)而對(duì)于閉包的定義是這樣說(shuō)的:當(dāng)函數(shù)可以記住并訪問(wèn)所在的作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前作用域之外執(zhí)行。

      for instance(拽個(gè)英文,哈哈)。

      function foo() {     var a = 2;     function bar() {         console.log(a);     }     bar(); } foo();

      上面的 代碼bar()可以訪問(wèn)外部作用域中的變量。根據(jù)上面的定義這是閉包嗎?從技術(shù)來(lái)講也許是,但我們理解的是作用域在當(dāng)前作用域查找變量如果沒(méi)找到會(huì)繼續(xù)向上面查找,找到返回,找不到繼續(xù)找,直到全局作用域。– 而這些正是閉包的一部分。函數(shù)bar()具有一個(gè)涵蓋foo()作用域的閉包。

      function foo(){    var a  = 2;    function bar (){         console.log(a);     }    return bar; }var baz = foo(); baz();

      在上面的代碼更好的展示了閉包。

      bar()函數(shù)在定義時(shí)作用域以外的地方執(zhí)行(此時(shí)在全局作用域執(zhí)行)。在foo()函數(shù)執(zhí)行后,通常會(huì)期待foo()整個(gè)內(nèi)部作用域都被銷毀,因?yàn)槲覀冎酪嬗?span style="background-color: #ccffcc;">垃圾回收器用來(lái)釋放不在使用的內(nèi)存空間,由于foo()已經(jīng)執(zhí)行完,看上去內(nèi)容不會(huì)再被使用,所以很自然的會(huì)考慮對(duì)齊進(jìn)行回收,回收后意味著里面的函數(shù)和變量訪問(wèn)不到了。foo()執(zhí)行完,baz變量存著bar函數(shù)的引用。當(dāng)執(zhí)行baz也就是bar函數(shù)時(shí)。console.log(a)。不理解閉包的人可能認(rèn)為會(huì)報(bào)錯(cuò),事實(shí)上,打印的是2;???what?

      foo()函數(shù)作用域不是執(zhí)行完銷毀了嗎?怎么還能訪問(wèn)到a變量?– 這就是閉包。

      當(dāng)foo()執(zhí)行后,bar函數(shù)被返回全局作用域下,但是bar函數(shù)還保留著當(dāng)時(shí)的詞法作用域(當(dāng)時(shí)寫(xiě)代碼是的順序就已經(jīng)定義了作用域,這個(gè)作用域叫詞法作用域–外面函數(shù)套著里面的函數(shù)的那種)甚至直到全局作用域。所以bar還留有foo()函數(shù)的引用。使得foo()函數(shù)沒(méi)有被回收。

      閉包可以說(shuō)不出不在,只是你沒(méi)有發(fā)現(xiàn)認(rèn)出他。在定時(shí)器,事件監(jiān)聽(tīng)器,ajax請(qǐng)求,跨窗口通信或者任何其他的異步(或者同步)任務(wù)中,只要使用了回調(diào)函數(shù),實(shí)際上就是使用閉包。

      for instance

      function wait(message) {     setTimeout(function timer() {         console.log(message);     }, 1000); } wait("hello");

      在上面的代碼中將一個(gè)內(nèi)部函數(shù)(名為timer)傳遞給setTimerout(…).timer具有涵蓋wait(…)的作用域的閉包。因此還保有對(duì)變量message的引用。wait()執(zhí)行1000毫秒后,它的內(nèi)部作用域不會(huì)消失,timer函數(shù)依然保有wait()作用域的閉包。

      而閉包和立即執(zhí)行函數(shù)息息相關(guān)。

      循環(huán)和閉包

      for(var i = 1; i <= 5; i++){     setTimeout(function timer(){         console.log(i);     },i*1000); }

      上面代碼我們以為輸出的會(huì)是1-5,可事實(shí)上輸出的是5個(gè)6,這是為啥啊 — 閉包啊。

      延遲函數(shù)的回調(diào)會(huì)在循環(huán)結(jié)束時(shí)執(zhí)行。事實(shí)上,當(dāng)定時(shí)器運(yùn)行時(shí)即使每個(gè)迭代的是setTimerout(…,0),所有的回調(diào)函數(shù)依然是循環(huán)結(jié)束后才會(huì)執(zhí)行。我猜是跟js執(zhí)行機(jī)制有關(guān)系吧。至于為什么都是6. 因?yàn)榧词?個(gè)函數(shù)是在各個(gè)迭代中分別定義的,但是他們又被封閉在一個(gè)共享的全局作用域中因此實(shí)際上只有一個(gè)i.而怎么解決呢,立即執(zhí)行函數(shù)來(lái)了?。?!

      for (var i = 1; i <= 5; i++) {     (function (i) {         setTimeout(function timer() {             console.log(i);         }, i * 1000);     })(i)  }

      打印出來(lái)1,2,3,4,5了歐,這回是你想要的數(shù)了。解釋一下,5次循環(huán)創(chuàng)建了5個(gè)立即執(zhí)行函數(shù),這5個(gè)函數(shù)的作用域都不相同,立即函數(shù)接收的參數(shù)是當(dāng)前循環(huán)的i.所以當(dāng)timer執(zhí)行時(shí)訪問(wèn)的就是自己立即執(zhí)行函數(shù)對(duì)應(yīng)的作用域。也就是說(shuō)5個(gè)timer函數(shù)分別對(duì)應(yīng)5個(gè)作用域,每個(gè)作用域保存的變量i都不同,解決啦?。。?/p>

      你懂閉包了嗎?

      js執(zhí)行機(jī)制

      JavaScript語(yǔ)言的一大特點(diǎn)就是單線程,也就是說(shuō),同一個(gè)時(shí)間只能做一件事。那么,為什么JavaScript不能有多個(gè)線程呢?這樣能提高效率啊。JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語(yǔ)言,JavaScript的主要用途是與用戶互動(dòng),以及操作DOM。這決定了它只能是單線程,否則會(huì)帶來(lái)很復(fù)雜的同步問(wèn)題。比如,假定JavaScript同時(shí)有兩個(gè)線程,一個(gè)線程在某個(gè)DOM節(jié)點(diǎn)上添加內(nèi)容,另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器應(yīng)該以哪個(gè)線程為準(zhǔn)所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成了這門語(yǔ)言的核心特征,將來(lái)也不會(huì)改變。

      單線程就意味著,所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。如果前一個(gè)任務(wù)耗時(shí)很長(zhǎng),后一個(gè)任務(wù)就不得不一直等著。JavaScript語(yǔ)言的設(shè)計(jì)者意識(shí)到這個(gè)問(wèn)題,將所有任務(wù)分成兩種,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)。同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù);異步任務(wù)指的是,不進(jìn)入主線程、而進(jìn)入"任務(wù)隊(duì)列"(task queue)的任務(wù),只有"任務(wù)隊(duì)列"通知主線程,某個(gè)異步任務(wù)可以執(zhí)行了,該任務(wù)才會(huì)進(jìn)入主線程執(zhí)行。

      主線程從"任務(wù)隊(duì)列"中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))。只要主線程空了,就會(huì)去讀取"任務(wù)隊(duì)列",這就是JavaScript的運(yùn)行機(jī)制。

      哪些語(yǔ)句會(huì)放入異步任務(wù)隊(duì)列及放入時(shí)機(jī)一般來(lái)說(shuō),有以下四種會(huì)放入異步任務(wù)隊(duì)列:setTimeout 和 setlnterval ,DOM事件,ES6中的Promise,Ajax異步請(qǐng)求

      本文來(lái)自 js教程 欄目,歡迎學(xué)習(xí)!

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)