最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

javascript作用域和閉包使用詳解

 更新時(shí)間:2014年04月25日 10:35:42   作者:  
這篇文章主要介紹了javascript作用域和閉包使用詳解,需要的朋友可以參考下

作用域的嵌套將形成作用域鏈,函數(shù)的嵌套將形成閉包。閉包與作用域鏈?zhǔn)?JavaScript 區(qū)別于其它語(yǔ)言的重要特性之一。

作用域
JavaScript 中有兩種作用域:函數(shù)作用域和全局作用域。

在一個(gè)函數(shù)中聲明的變量以及該函數(shù)的參數(shù)享有同一個(gè)作用域,即函數(shù)作用域。一個(gè)簡(jiǎn)單的函數(shù)作用域的例子:

復(fù)制代碼 代碼如下:

function foo() {
    var bar = 1;
    {
        var bar = 2;
    }
    return bar; // 2
}

不同于C等其它有塊作用域的語(yǔ)言,這里將始終返回 2 。

全局作用域,對(duì)于瀏覽器來(lái)說(shuō)可以理解為 window 對(duì)象(Node.js則是 global):

復(fù)制代碼 代碼如下:

var bar = 1;
function foo() {}
alert(window.bar); // 1
alert(window.foo); // "function foo() {}"

對(duì)于變量 bar 和函數(shù) foo 都屬于全局作用域,都是 window 的一個(gè)屬性。

作用域鏈
在 JavaScript 中訪問(wèn)一個(gè)變量時(shí),將從本地變量和參數(shù)開始,逐級(jí)向上遍歷作用域直到全局作用域。

復(fù)制代碼 代碼如下:

var scope = 0, zero = "global-scope";
(function(){
    var scope = 1, one = "scope-1";
    (function(){
        var scope = 2, two = "scope-2";
        (function(){
            var scope = 3, three = "scope-3";
            // scope-3 scope-2 scope-1 global-scope
            console.log([three, two, one, zero].join(" "));
            console.log(scope); // 3
        })();
        console.log(typeof three); // undefined
        console.log(scope); // 2
    })();
    console.log(typeof two); // undefined
    console.log(scope); // 1
})();
console.log(typeof one); // undefined
console.log(scope); // 0

在最里層的函數(shù)中,各個(gè)變量都能被逐級(jí)遍歷并輸出。而倒數(shù)第二層的函數(shù)中,變量 three 無(wú)法遍歷找到,所以輸出了 undefined 。

舉一個(gè)通俗點(diǎn)的例子,你準(zhǔn)備要花錢買點(diǎn)東西時(shí),會(huì)先摸摸自己的錢包,沒(méi)了你可以找你爸要,你爸也沒(méi)有就再找你爺爺,... 。而你爸沒(méi)錢買東西時(shí),他并不會(huì)來(lái)找你要。

閉包
在一個(gè)函數(shù)中,定義另一個(gè)函數(shù),稱為函數(shù)嵌套。函數(shù)的嵌套將形成一個(gè)閉包。

閉包與作用域鏈相輔相成,函數(shù)的嵌套在產(chǎn)生了鏈?zhǔn)疥P(guān)系的多個(gè)作用域的同時(shí),也形成了一個(gè)閉包。

復(fù)制代碼 代碼如下:

function bind(func, target) {
    return function() {
        func.apply(target, arguments);
    };
}

那么怎么理解閉包呢?

外部函數(shù)不能訪問(wèn)內(nèi)嵌函數(shù)
外部函數(shù)也不能訪問(wèn)內(nèi)嵌函數(shù)的參數(shù)和變量
而內(nèi)嵌函數(shù)可以訪問(wèn)外部函數(shù)的參數(shù)和變量
換一個(gè)說(shuō)法:內(nèi)嵌函數(shù)包含了外部函數(shù)的作用域
我們?cè)倏纯粗爸v述的作用域鏈的例子,這次從閉包的角度來(lái)理解下:

復(fù)制代碼 代碼如下:

var scope = 0, zero = "global-scope";
(function(){
    var scope = 1, one = "scope-1";
    (function(){
        var scope = 2, two = "scope-2";
        (function(){
            var scope = 3, three = "scope-3";
            // scope-3 scope-2 scope-1 global-scope
            console.log([three, two, one, zero].join(" "));
            console.log(scope); // 3
        })();
        console.log(typeof three); // undefined
        console.log(scope); // 2
    })();
    console.log(typeof two); // undefined
    console.log(scope); // 1
})();
console.log(typeof one); // undefined
console.log(scope); // 0

最里層的函數(shù)能訪問(wèn)到其內(nèi)部和外部定義的所有變量。而倒數(shù)第二層的函數(shù)無(wú)法訪問(wèn)到最里層的變量,同時(shí),最里層的 scope = 3 這個(gè)賦值操作并沒(méi)有對(duì)其外部的同名變量產(chǎn)生影響。

再換個(gè)角度來(lái)理解閉包:

每次外部函數(shù)的調(diào)用,內(nèi)嵌函數(shù)都會(huì)被創(chuàng)建一次
在它被創(chuàng)建時(shí),外部函數(shù)的作用域(包括任何本地變量、參數(shù)等上下文), 會(huì)成為每個(gè)內(nèi)嵌函數(shù)對(duì)象的內(nèi)部狀態(tài)的一部分,即使在外部函數(shù)執(zhí)行完并退出后
看下面的例子:

復(fù)制代碼 代碼如下:

var i, list = [];
for (i = 0; i < 2; i += 1) {
    list.push(function(){
        console.log(i);
    });
}
list.forEach(function(func){
  func();
});

我們將得到兩次 "2" ,而不是預(yù)期的 "1" 和 "2" ,這是因?yàn)樵?list 中的兩個(gè)函數(shù)訪問(wèn)的變量 i 都是其上一層作用域的同一個(gè)變量。

我們改動(dòng)下代碼,以利用閉包來(lái)解決這個(gè)問(wèn)題:

復(fù)制代碼 代碼如下:

var i, list = [];
for (i = 0; i < 2; i += 1) {
    list.push((function(j){
        return function(){
            console.log(j);
        };
    })(i));
}
list.forEach(function(func){
  func();
});

外層的“立即執(zhí)行函數(shù)”接收了一個(gè)參數(shù)變量 i ,在其函數(shù)內(nèi)以參數(shù) j 的形式存在,它與被返回的內(nèi)層函數(shù)中的名稱 j 指向同一個(gè)引用。外層函數(shù)執(zhí)行并退出后,參數(shù) j (此時(shí)它的值為 i 的當(dāng)前值)成為了其內(nèi)層函數(shù)的狀態(tài)的一部分被保存了下來(lái)。

相關(guān)文章

  • Javascript學(xué)習(xí)筆記之?dāng)?shù)組的遍歷和 length 屬性

    Javascript學(xué)習(xí)筆記之?dāng)?shù)組的遍歷和 length 屬性

    我們一般用循環(huán)來(lái)遍歷數(shù)組,而循環(huán)一直是 JavaScript 性能問(wèn)題的常見來(lái)源,有時(shí)循環(huán)用得不好會(huì)嚴(yán)重降低代碼的運(yùn)行速度。數(shù)組的屬性可以分為三種:length屬性,索引屬性,其他屬性.和普通對(duì)象相比,數(shù)組對(duì)象特殊的地方就是它的length屬性和索引屬性。
    2014-11-11
  • JavaScript數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹詳解

    JavaScript數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹詳解

    這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹詳解,本文講解了二叉樹的概念、二叉樹的特點(diǎn)、二叉樹節(jié)點(diǎn)的定義、查找最大和最小值等內(nèi)容,需要的朋友可以參考下
    2015-02-02
  • js中值類型和引用類型的區(qū)別介紹

    js中值類型和引用類型的區(qū)別介紹

    這篇文章介紹了js中值類型和引用類型的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 總結(jié)javascript三元運(yùn)算符知識(shí)點(diǎn)

    總結(jié)javascript三元運(yùn)算符知識(shí)點(diǎn)

    這是一篇關(guān)于javascript三元運(yùn)算符的相關(guān)基礎(chǔ)知識(shí)點(diǎn)內(nèi)容,大家可以學(xué)習(xí)一下鞏固基礎(chǔ)知識(shí)。
    2018-09-09
  • JavaScript 函數(shù)模式詳解及示例

    JavaScript 函數(shù)模式詳解及示例

    本文主要介紹JavaScript 函數(shù)模式,這里整理了詳細(xì)的資料及簡(jiǎn)單示例代碼,幫助大家學(xué)習(xí)參考此部分的知識(shí),有興趣的小伙伴可以參考下
    2016-09-09
  • javascript中this指向詳解

    javascript中this指向詳解

    this的指向在函數(shù)定義的時(shí)候是確定不了的,只有函數(shù)執(zhí)行的時(shí)候才能確定this到底指向誰(shuí),實(shí)際上this的最終指向的是那個(gè)調(diào)用它的對(duì)象,接下來(lái)我會(huì)深入的探討這個(gè)問(wèn)題。
    2016-04-04
  • form表單序列化詳解(推薦)

    form表單序列化詳解(推薦)

    這篇文章主要介紹了form表單序列化操作,通過(guò)將表單中的鍵值序列化為可提交的字符串,并附上代碼實(shí)例詳細(xì)講解了運(yùn)行之后的結(jié)果,需要的朋友可以參考下
    2017-08-08
  • 深入解析JavaScript中的數(shù)字對(duì)象與字符串對(duì)象

    深入解析JavaScript中的數(shù)字對(duì)象與字符串對(duì)象

    這篇文章主要介紹了JavaScript中的數(shù)字對(duì)象與字符串對(duì)象,是JavaScript入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • 解析js中獲得父窗口鏈接getParent方法以及各種打開窗口的方法

    解析js中獲得父窗口鏈接getParent方法以及各種打開窗口的方法

    本篇文章是對(duì)js中獲得父窗口鏈接getParent方法以及各種打開窗口的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 在瀏覽器中打開或關(guān)閉JavaScript的方法

    在瀏覽器中打開或關(guān)閉JavaScript的方法

    這篇文章主要介紹了在瀏覽器中打開或關(guān)閉JavaScript的方法,由于歷史遺留問(wèn)題,JS在目前任何瀏覽器中都是標(biāo)配...所以不想加載JS也可以選擇關(guān)閉,需要的朋友可以參考下
    2015-06-06

最新評(píng)論

太仆寺旗| 阳曲县| 金湖县| 揭西县| 义马市| 万全县| 响水县| 尚志市| 天柱县| 尼勒克县| 天镇县| 和田县| 沾化县| 龙门县| 商河县| 赤城县| 民权县| 蒙自县| 崇左市| 黄浦区| 中江县| 介休市| 勐海县| 富阳市| 陇西县| 全椒县| 弋阳县| 长汀县| 新兴县| 文水县| 金坛市| 西乌| 灵川县| 蓬莱市| 桦川县| 达日县| 易门县| 徐汇区| 新疆| 濮阳市| 大连市|