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

資訊專(zhuān)欄INFORMATION COLUMN

javaScript作用域與閉包

Reducto / 1425人閱讀

摘要:閉包里面保存的變量只有被方法引用了的變量這個(gè)例子里,閉包里只有并沒(méi)有。那最后來(lái)說(shuō)說(shuō)的問(wèn)題閉包到底是什么閉包是一個(gè)作用域。鑒于在的調(diào)試窗口,是放在下面的那閉包這個(gè)作用域是個(gè)什么范圍被后代方法子方法,孫子方法。。。

首先給js的作用域這個(gè)話題打標(biāo)簽:2,var, 全局變量,局部變量,函數(shù),undefined, 作用域提升,賦值不會(huì)提升,ReferenceError, 同名覆蓋。
打完標(biāo)簽之后,我們來(lái)說(shuō)跟作用域有關(guān)的幾條鐵打的規(guī)則:
1: JS的作用域有2種:全局作用域,函數(shù)作用域。

把作用域想象成一個(gè)房間,而{}是房間的門(mén)。門(mén)上裝了一個(gè)貓眼,所以房間里面可以看清楚外面,但是外面卻看不見(jiàn)里面。
在JAVA或者C里面,大括號(hào)可能會(huì)出現(xiàn)的情況有兩種:
    1: 一個(gè)function定義的時(shí)候
    2: 一個(gè)塊定義(比如if,for, while)的時(shí)候.
所以此時(shí)的作用域有三種類(lèi)型:
    1: 全局作用域,
    2: 函數(shù)作用域
    3: 塊級(jí)作用域。

但是在JS里面,雖然{}出現(xiàn)的情況也有兩種,但是只有function的{}才起到柵欄的作用。

2: 聲明在全局作用域里的變量是全局變量,聲明在函數(shù)里面的變量是局部變量

3: 怎么創(chuàng)造一個(gè)全局變量和局部變量?

創(chuàng)造全局變量的方法有兩種:

   1: 在全局作用域內(nèi)用var定義: var a;
   2: 聲明一個(gè)變量,不帶var(無(wú)論是在全局,在函數(shù)里面還是在一個(gè)塊里面):b

創(chuàng)造局部變量的方法只有一種:

   在函數(shù)體里面,帶var聲明一個(gè)變量: function func(){var b;}

3: 使用一個(gè)沒(méi)有聲明過(guò)的變量,會(huì)得到一個(gè)ReferenceError。無(wú)論什么情況下。
4: 不同作用域內(nèi),同名的變量,越小的作用域的變量會(huì)覆蓋越大的作用域的。

4: 作用域提升:變量在聲明之前就可以引用了!
這個(gè)不是和第三點(diǎn)矛盾了嗎?其實(shí)并沒(méi)有。它背后的真正原理是:并不是作用域被提升(我們前面說(shuō)了,一個(gè)變量的作用域會(huì)被框在一對(duì)柵欄{}里面,一旦這個(gè)柵欄確定了,那這個(gè)作用域是不可能變化的),其實(shí)是變量的‘聲明’在其作用域里面被放到任何代碼之前(當(dāng)然包括引用它的代碼之前)??匆欢未a:

var scope = "global";
function func(){
    console.log(scope); //輸出‘undefined’,而不是‘global’
    var scope = "local";
    console.log(scope); //輸出‘local’
}

看到第一個(gè)console,可能以為會(huì)輸出‘global’, 因?yàn)橥ㄟ^(guò)貓眼可以看見(jiàn)外面的變量。但是,一旦我們進(jìn)到一個(gè)函數(shù)體里面,遇到任何的變量的引用,首先要先在當(dāng)前的房間里面找,只有在當(dāng)前的房間里面找不到時(shí),才到父層去找。那為什么是‘undefined呢?其實(shí)以上的代碼等價(jià)于:

var scope = "global";
function func(){
    var scope; //變量的聲明會(huì)提升到最前面,但是賦值并不會(huì),所以此刻scope的值還只是undefined.
    console.log(scope); //輸出‘undefined’,而不是‘global’
    scope = "local"; //賦值在這里完成
    console.log(scope); //輸出‘local’
}

============閉包的分割線===========
1: 什么是閉包?
我看過(guò)看多不同的書(shū),對(duì)必包的定義都不一樣,而且就算是我知道了閉包的定義,對(duì)我真正理解它的工作原理還是沒(méi)有什么用。所以,我就不去糾結(jié)它到底是什么,我接下來(lái)只關(guān)注它是怎么工作的。
2: 什么時(shí)候會(huì)形成閉包?
以下內(nèi)容非原創(chuàng),這里只是我自己的一個(gè)學(xué)習(xí)筆記。我看了http://www.jianshu.com/p/7312...(在這里感謝作者),跟著文章里面的例子(代碼根據(jù)自己的喜好改了一些)走一遍:
1: When? 閉包出現(xiàn)的時(shí)刻?

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

在斷點(diǎn)的過(guò)程中,運(yùn)行完第9行代碼的時(shí)候,調(diào)試窗口里并沒(méi)有出現(xiàn)任何閉包;直到我運(yùn)行了第10行代碼,跳到第5行的時(shí)候(也就是baz這個(gè)方法被調(diào)用的時(shí)候),調(diào)試窗口出現(xiàn)了閉包(Closure)。并且可以看到說(shuō)foo是closure, 它包含一個(gè)變量a,值為2。

結(jié)論1:雖然很多書(shū)上說(shuō)閉包跟函數(shù)定義的時(shí)候的作用域有關(guān),跟它執(zhí)行時(shí)候的作用域無(wú)關(guān),但是它在瀏覽器里面出現(xiàn)的時(shí)機(jī)卻是在執(zhí)行的時(shí)候。

2 How? 閉包出現(xiàn)的條件?

function foo() {
    var a = 2;
    function baz(m) { 
        console.log(m);
    }
    return baz;
}
var fn = foo()
fn(20); //20

很多地方都說(shuō)在方法里面定義方法就會(huì)形成閉包,但是在這里例子里面,我執(zhí)行完第10行的代碼,調(diào)試窗口并沒(méi)有出現(xiàn)任何閉包。和例1的差別在于,baz沒(méi)有引用變量a.

結(jié)論2:一個(gè)方法,一定要引用其父層方法(非自己方法內(nèi)部的變量)的變量才會(huì)形成閉包。

但是閉包的形成是不是一定要執(zhí)行到引用了父層作用域變量的方法才出現(xiàn)呢?看下面一個(gè)例子:

3: 當(dāng)父層方法里有不只一個(gè)方法

function foo() {
    var a = 10;
    var b = 30;

    function fn1() {
        return a;
    }

    function fn2() {
        return 20;
    }

    return fn2;
}

var fn = foo();
fn();



當(dāng)我執(zhí)行到17行然后跳進(jìn)其方法體(第10行)的時(shí)候,調(diào)試窗口出現(xiàn)了Closure, 并且它有一個(gè)變量a,
值為10。其實(shí)這個(gè)例子說(shuō)明了兩個(gè)事情:

結(jié)論3: 在執(zhí)行一個(gè)定義在方法里面的方法時(shí),即使它的方法體自己沒(méi)有引用父層變量,但是只要有任何兄弟方法引用了,那就會(huì)形成閉包。閉包里面保存的變量只有被方法引用了的變量(這個(gè)例子里,閉包里只有a,并沒(méi)有b)。
4: 當(dāng)不是兄弟方法,而是子方法引用了父級(jí)變量,會(huì)發(fā)生什么情況呢?

function foo() {
    var a = 10;
    var b = 30;

    function fn1() {
        var c = 20;
        function fn2(){
            return a;
        }
        return fn2;
    }

    return fn1;
}

var fn1 = foo();
var fn2 = fn1();
fn2();

fn1方法體內(nèi)沒(méi)有引用任何的父層變量,但是它的子方法fn2引用了變量a。在調(diào)試的過(guò)程中,當(dāng)執(zhí)行到f1的時(shí)候(執(zhí)行到第6行,這時(shí)候可以看到變量c都還是"undefined"),Closure就已經(jīng)出現(xiàn)了,并不像之前那樣一定要等到執(zhí)行fn2.最后看一個(gè)例子:

5: 當(dāng)不是直系子方法,而是侄子方法引用了父級(jí)變量

function foo() {
    var a = 10;
    var b = 30;

    function fn1() {
        var c = 20;
        function fn2(){
            return a;
        }
        return fn2;
    }
    function fn3(){
        return 40;
    }

    return fn3;
}
    
var fn3 = foo();
fn3();
    

當(dāng)執(zhí)行到調(diào)用fn3的時(shí)候,Chosure出現(xiàn)了。所以閉包到底是在什么時(shí)候形成呢?在我們前面的結(jié)論里面有提到說(shuō)方法執(zhí)行的時(shí)候,但是經(jīng)過(guò)后面的這幾個(gè)例子說(shuō)明并不一定非得是執(zhí)行的時(shí)候,而且JavaScript是基于詞法作用域的語(yǔ)言(變量的作用域在其定義的時(shí)候就已經(jīng)確定了,不依賴于執(zhí)行時(shí)的環(huán)境),所以我傾向于閉包(Closure)是在方法定義的時(shí)候就形成了的。那最后來(lái)說(shuō)說(shuō)What的問(wèn)題:閉包到底是什么?
1: 閉包是一個(gè)作用域。(鑒于在Chrome的調(diào)試窗口,Closure是放在Scope下面的)
2: 那閉包這個(gè)作用域是個(gè)什么范圍:被后代方法(子方法,孫子方法。。。)所引用的變量所在的作用域(或者說(shuō)這個(gè)變量所在的方法)。
3: 閉包里面有什么:只包含被后代方法所引用了的變量,并不包含這個(gè)變量的兄弟姐妹。
4: 上面的所有例子都只引用了變量,換成方法,也都是同樣的結(jié)果。
真的是最后一個(gè)例子了:

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

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

相關(guān)文章

  • Javascript重溫OOP之作用域與閉包

    摘要:的變量作用域是基于其特有的作用域鏈的。需要注意的是,用創(chuàng)建的函數(shù),其作用域指向全局作用域。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。 作用域 定義 在編程語(yǔ)言中,作用域控制著變量與參數(shù)的可見(jiàn)性及生命周期,它能減少名稱(chēng)沖突,而且提供了自動(dòng)內(nèi)存管理 --javascript 語(yǔ)言精粹 我理解的是,一個(gè)變量、函數(shù)或者成員可以在代碼中訪問(wèn)到的范圍。 js的變量作...

    JessYanCoding 評(píng)論0 收藏0
  • Javascript中的作用域與閉包

    摘要:作用域分為詞法作用域和動(dòng)態(tài)作用域。這樣就形成了一個(gè)鏈?zhǔn)降淖饔糜?。一般情況下,當(dāng)函數(shù)執(zhí)行完畢時(shí),里面的變量會(huì)被自動(dòng)銷(xiāo)毀。而能夠訪問(wèn)到這個(gè)在的編譯階段就已經(jīng)定型了詞法作用域。 什么是作用域?在當(dāng)前運(yùn)行環(huán)境下,可以訪問(wèn)的變量或函數(shù)的范圍。作用域分為詞法作用域和動(dòng)態(tài)作用域。詞法作用域是在js代碼編譯階段就確定下來(lái)的; 對(duì)應(yīng)的,with和eval語(yǔ)句會(huì)產(chǎn)生動(dòng)態(tài)作用域。 會(huì)產(chǎn)生新的作用域的情況: ...

    tianren124 評(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)這是一道考作用域的題目,...

    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

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

0條評(píng)論

閱讀需要支付1元查看
<