成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

詞法作用域與閉包

張金寶 / 2181人閱讀

摘要:我們可以這么解決問(wèn)題在上述代碼中,每次遍歷我們都使用生成一個(gè)新的作用域,使得延遲函數(shù)的回調(diào)可以將新的作用域封閉在每個(gè)迭代內(nèi)部,每個(gè)迭代中都會(huì)含有一個(gè)具有正確值的變量供我們?cè)L問(wèn)。

首先需要明確的是,javascript 中沒(méi)有塊作用域,只有函數(shù)作用域
到底什么是閉包?
function foo() {
    var a = 2;

    function bar() {
        console.log(a); // 2
    }

    bar();
}

foo();

這是閉包嗎?
技術(shù)上來(lái)講也許是,但確切地說(shuō)并不是。

我認(rèn)為最準(zhǔn)確地用來(lái)解釋 bar() 對(duì) a 的引用的方法是詞法作用域的查找規(guī)則,而這些規(guī)則只是閉包的一部分。(但卻是非常重要的一部分!)
function foo() {
    var a = 2;

    function bar() {
        console.log(a); // 2
    }

    return bar;
}

var baz = foo();

baz(); // 2

這才是閉包的效果!
在上例中函數(shù) bar 在定義自己的詞法作用域以外的地方執(zhí)行,在 foo 執(zhí)行后垃圾回收器不知道 bar 什么時(shí)候會(huì)被調(diào)用,這使得對(duì) foo 內(nèi)部作用域的回收工作被阻止,而 bar 依然持有對(duì)該作用域的引用,這個(gè)引用就叫做閉包。

無(wú)論通過(guò)何種手段將內(nèi)部函數(shù)傳遞到所在的詞法作用域以外,它都會(huì)持有對(duì)原始定義作用域的引用,無(wú)論在何處執(zhí)行這個(gè)函數(shù)都會(huì)使用閉包。
循環(huán)與閉包

要說(shuō)明閉包,for 循環(huán)是最常見(jiàn)的例子。

for (var i = 0; i < 10; i++) {
    console.log(i);
}

執(zhí)行上述代碼我們可以打印出0到9十個(gè)數(shù)字,但是如果執(zhí)行下面這段代碼呢?

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

正常情況下,我們對(duì)這段代碼行為的預(yù)期是分別輸出數(shù)字 1~5,每秒一次,每次一個(gè)。
但實(shí)際上,這段代碼在運(yùn)行時(shí)會(huì)以每秒一次的頻率輸出五次 6。

我們可以這么理解問(wèn)題:眾所周知 javascript 是解釋型的單線程編程語(yǔ)言,上述代碼的執(zhí)行過(guò)程實(shí)際是,執(zhí)行 for 循環(huán)并把5個(gè)匿名函數(shù)的觸發(fā)分別間隔 1-5 秒放入異步隊(duì)列當(dāng)中,而當(dāng)異步隊(duì)列的頭節(jié)點(diǎn)開(kāi)始執(zhí)行時(shí),for 循環(huán)早已經(jīng)執(zhí)行完畢,并且此時(shí) i 作為全局作用域中的變量,其值為 6,這時(shí)無(wú)論異步隊(duì)列中的頭節(jié)點(diǎn)還是尾節(jié)點(diǎn),在打印 i 變量的值并試圖向上層作用域查找 i 時(shí),獲得的結(jié)果都是 6。

我們可以這么解決問(wèn)題!

for (var i = 1; i <= 5; i++) {
    (function(j) {
        setTimeout(function timer() {
            console.log(j);
        }, j * 1000);
    })(i);
}
在上述代碼中,每次遍歷我們都使用 IIFE 生成一個(gè)新的作用域,使得延遲函數(shù)的回調(diào)可以將新的
作用域封閉在每個(gè)迭代內(nèi)部,每個(gè)迭代中都會(huì)含有一個(gè)具有正確值的變量供我們?cè)L問(wèn)。

用容易理解的語(yǔ)言可以這么描述:IIFE 在執(zhí)行完畢后,不知道延遲函數(shù)的回調(diào)什么時(shí)候執(zhí)行,所以 IIFE 的作用域無(wú)法被銷毀,其 j 變量的值被鎖住。

塊作用域與閉包

熟悉 ES6 的同學(xué)們都知道,下述代碼也可以解決上面的 for 循環(huán)問(wèn)題:

for (let i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i);
    }, i * 1000);
}
for (let i = 1; i <= 5; i++) 這行代碼的圓括號(hào)之間存在一個(gè)隱藏的作用域,在每次執(zhí)行循環(huán)體之前,javascript 引擎會(huì)把 i 在循環(huán)體的上下文中重新聲明及初始化一次。

看到這兒我想大家應(yīng)該有一個(gè)比較清楚的認(rèn)識(shí):解決 for 循環(huán)問(wèn)題的根本是 塊作用域!無(wú)論是 let/const 還是閉包,其本質(zhì)都是在每次遍歷時(shí)構(gòu)建一個(gè)塊作用域。

至少?gòu)?ES3 發(fā)布以來(lái),javaScript 中就有了塊作用域,而 withcatch 分句就是塊作用域的兩個(gè)小例子。

附錄

Tip: let 存在提升,只不過(guò)由于暫時(shí)死區(qū)的限制,不能在 let x 之前使用 x。

let 的「創(chuàng)建」過(guò)程被提升,但是初始化沒(méi)有提升

var 的「創(chuàng)建」和「初始化」都被提升

function 的「創(chuàng)建」「初始化」和「賦值」都被提升

const 和 let 只有一個(gè)區(qū)別,那就是 const 只有「創(chuàng)建」和「初始化」,沒(méi)有「賦值」過(guò)程

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83211.html

相關(guān)文章

  • Js基礎(chǔ)知識(shí)(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說(shuō)為其聲明的變量隱式的劫持了所在的塊級(jí)作用域。 作用域與閉包 如何用js創(chuàng)建10個(gè)button標(biāo)簽,點(diǎn)擊每個(gè)按鈕時(shí)打印按鈕對(duì)應(yīng)的序號(hào)? 看到上述問(wèn)題,如果你能看出來(lái)這個(gè)問(wèn)題實(shí)質(zhì)上是考對(duì)作用域的理解,那么恭喜你,這篇文章你可以不用看了,說(shuō)明你對(duì)作用域已經(jīng)理解的很透徹了,但是如果你看不出來(lái)這是一道考作用域的題目,...

    lemanli 評(píng)論0 收藏0
  • Js基礎(chǔ)知識(shí)(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說(shuō)為其聲明的變量隱式的劫持了所在的塊級(jí)作用域。 作用域與閉包 如何用js創(chuàng)建10個(gè)button標(biāo)簽,點(diǎn)擊每個(gè)按鈕時(shí)打印按鈕對(duì)應(yīng)的序號(hào)? 看到上述問(wèn)題,如果你能看出來(lái)這個(gè)問(wèn)題實(shí)質(zhì)上是考對(duì)作用域的理解,那么恭喜你,這篇文章你可以不用看了,說(shuō)明你對(duì)作用域已經(jīng)理解的很透徹了,但是如果你看不出來(lái)這是一道考作用域的題目,...

    XFLY 評(píng)論0 收藏0
  • Js基礎(chǔ)知識(shí)(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說(shuō)為其聲明的變量隱式的劫持了所在的塊級(jí)作用域。 作用域與閉包 如何用js創(chuàng)建10個(gè)button標(biāo)簽,點(diǎn)擊每個(gè)按鈕時(shí)打印按鈕對(duì)應(yīng)的序號(hào)? 看到上述問(wèn)題,如果你能看出來(lái)這個(gè)問(wèn)題實(shí)質(zhì)上是考對(duì)作用域的理解,那么恭喜你,這篇文章你可以不用看了,說(shuō)明你對(duì)作用域已經(jīng)理解的很透徹了,但是如果你看不出來(lái)這是一道考作用域的題目,...

    tanglijun 評(píng)論0 收藏0
  • Js基礎(chǔ)知識(shí)(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說(shuō)為其聲明的變量隱式的劫持了所在的塊級(jí)作用域。 作用域與閉包 如何用js創(chuàng)建10個(gè)button標(biāo)簽,點(diǎn)擊每個(gè)按鈕時(shí)打印按鈕對(duì)應(yīng)的序號(hào)? 看到上述問(wèn)題,如果你能看出來(lái)這個(gè)問(wèn)題實(shí)質(zhì)上是考對(duì)作用域的理解,那么恭喜你,這篇文章你可以不用看了,說(shuō)明你對(duì)作用域已經(jīng)理解的很透徹了,但是如果你看不出來(lái)這是一道考作用域的題目,...

    lmxdawn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

張金寶

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<