亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript作用域和閉包使用詳解

2019-11-20 20:47:16
字體:
來源:轉載
供稿:網友

作用域的嵌套將形成作用域鏈,函數的嵌套將形成閉包。閉包與作用域鏈是 JavaScript 區別于其它語言的重要特性之一。

作用域
JavaScript 中有兩種作用域:函數作用域和全局作用域。

在一個函數中聲明的變量以及該函數的參數享有同一個作用域,即函數作用域。一個簡單的函數作用域的例子:

復制代碼 代碼如下:

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

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

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

復制代碼 代碼如下:

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

對于變量 bar 和函數 foo 都屬于全局作用域,都是 window 的一個屬性。

作用域鏈
在 JavaScript 中訪問一個變量時,將從本地變量和參數開始,逐級向上遍歷作用域直到全局作用域。

復制代碼 代碼如下:

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

在最里層的函數中,各個變量都能被逐級遍歷并輸出。而倒數第二層的函數中,變量 three 無法遍歷找到,所以輸出了 undefined 。

舉一個通俗點的例子,你準備要花錢買點東西時,會先摸摸自己的錢包,沒了你可以找你爸要,你爸也沒有就再找你爺爺,... 。而你爸沒錢買東西時,他并不會來找你要。

閉包
在一個函數中,定義另一個函數,稱為函數嵌套。函數的嵌套將形成一個閉包。

閉包與作用域鏈相輔相成,函數的嵌套在產生了鏈式關系的多個作用域的同時,也形成了一個閉包。

復制代碼 代碼如下:

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

那么怎么理解閉包呢?

外部函數不能訪問內嵌函數
外部函數也不能訪問內嵌函數的參數和變量
而內嵌函數可以訪問外部函數的參數和變量
換一個說法:內嵌函數包含了外部函數的作用域
我們再看看之前講述的作用域鏈的例子,這次從閉包的角度來理解下:

復制代碼 代碼如下:

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

最里層的函數能訪問到其內部和外部定義的所有變量。而倒數第二層的函數無法訪問到最里層的變量,同時,最里層的 scope = 3 這個賦值操作并沒有對其外部的同名變量產生影響。

再換個角度來理解閉包:

每次外部函數的調用,內嵌函數都會被創建一次
在它被創建時,外部函數的作用域(包括任何本地變量、參數等上下文), 會成為每個內嵌函數對象的內部狀態的一部分,即使在外部函數執行完并退出后
看下面的例子:

復制代碼 代碼如下:

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

我們將得到兩次 "2" ,而不是預期的 "1" 和 "2" ,這是因為在 list 中的兩個函數訪問的變量 i 都是其上一層作用域的同一個變量。

我們改動下代碼,以利用閉包來解決這個問題:

復制代碼 代碼如下:

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();
});

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美成人区| 国产91九色视频| 亚洲第一精品夜夜躁人人爽| 亚洲人成网站免费播放| 日韩精品在线免费观看视频| 亚洲免费影视第一页| 久久久国产精品视频| 欧美国产精品人人做人人爱| 欧美激情第三页| 亚洲大胆人体视频| 亚洲国产精品美女| 91精品一区二区| 91高清在线免费观看| 清纯唯美亚洲激情| 搡老女人一区二区三区视频tv| 97国产一区二区精品久久呦| 亚洲欧美www| 国产精品草莓在线免费观看| 98精品国产高清在线xxxx天堂| 在线播放精品一区二区三区| www.午夜精品| 91精品国产九九九久久久亚洲| 欧美做爰性生交视频| 欧美大秀在线观看| 亚洲a成v人在线观看| 精品国偷自产在线视频| 亚洲精品美女久久久| 98精品国产自产在线观看| 一区二区亚洲欧洲国产日韩| 亚洲bt欧美bt日本bt| 欧美极品xxxx| 精品久久久久久久久久久| 日韩欧美国产一区二区| 欧美国产日产韩国视频| 国产香蕉97碰碰久久人人| 色噜噜狠狠狠综合曰曰曰88av| 午夜精品一区二区三区视频免费看| 亚洲在线免费观看| 热re99久久精品国产66热| 国产亚洲精品美女久久久久| 亚洲精品国产电影| 中文字幕免费精品一区高清| 日韩精品视频在线免费观看| 久久综合国产精品台湾中文娱乐网| 国产精品露脸av在线| 亚洲一区二区中文字幕| 中文字幕欧美精品在线| 综合av色偷偷网| 国产视频精品免费播放| 国产精品入口夜色视频大尺度| 欧美中文字幕第一页| 国产精品成人品| 亚洲精品美女免费| 欧美精品一二区| 成人国产在线激情| 亚洲精品永久免费精品| 国产精品免费在线免费| 国色天香2019中文字幕在线观看| 亚洲精品福利在线观看| 亚洲精品成人av| 久久久女女女女999久久| 中文字幕亚洲自拍| 亚洲精品欧美日韩| 欧美精品激情视频| 国产精品久久久久秋霞鲁丝| 91成人免费观看网站| 色噜噜国产精品视频一区二区| 日韩激情视频在线播放| 亚洲欧美中文日韩v在线观看| 欧美精品videossex性护士| 国产精品福利小视频| 国产精品视频一区二区高潮| 国产精品电影网站| 国产精品午夜视频| 隔壁老王国产在线精品| xx视频.9999.com| 久久久亚洲欧洲日产国码aⅴ| 久久影视电视剧凤归四时歌| 午夜精品一区二区三区在线| 成人黄色av网| 国产一区二区色| 久久亚洲综合国产精品99麻豆精品福利| 亚洲一区二区久久久久久久| 亚洲欧美在线免费观看| 亚洲精品欧美日韩专区| 亚洲人精选亚洲人成在线| 91精品国产高清久久久久久91| 日韩少妇与小伙激情| 91网在线免费观看| 中文在线资源观看视频网站免费不卡| 成人久久一区二区| 国产精品久久久久久超碰| 国产精品高清在线| 欧美夫妻性生活xx| 久久精品国产一区二区三区| 国产黑人绿帽在线第一区| 国产精品久久久久av免费| 欧美日本高清视频| 久久视频在线免费观看| 97国产一区二区精品久久呦| 久久久国产精彩视频美女艺术照福利| 欧美黑人xxx| 亚洲国产精品高清久久久| 亚洲色图校园春色| 97精品一区二区视频在线观看| 亚洲成人黄色网址| 欧美激情精品久久久| 亚洲天堂av在线免费| 26uuu另类亚洲欧美日本老年| 日韩一二三在线视频播| 国产一区二区三区视频在线观看| 日韩电影中文字幕av| 国产精品69av| 亚洲丝袜在线视频| 一区二区亚洲精品国产| 欧美激情精品久久久久久久变态| 久久99国产精品自在自在app| 日韩av在线免费播放| 欧美激情a在线| 性色av一区二区三区| 久久精品精品电影网| 人人澡人人澡人人看欧美| 国产女人精品视频| 久久成人国产精品| 中文字幕视频在线免费欧美日韩综合在线看| 久久福利网址导航| 欧美丝袜一区二区三区| 日韩精品福利网站| 国产精品v日韩精品| 亚洲免费视频一区二区| 国产欧美精品一区二区| 日韩精品在线视频美女| 欧美成人中文字幕| 精品福利视频导航| 亚洲最大福利视频网| 日韩av免费在线观看| 不卡av日日日| 中文字幕亚洲第一| 欧美国产日韩xxxxx| 国产精品久久久久久久久久久久久久| 亚洲r级在线观看| 国内外成人免费激情在线视频网站| 久久影视电视剧免费网站| 久久精品电影网| 亚洲码在线观看| 日韩在线高清视频| 亚洲老头同性xxxxx| 国模精品视频一区二区三区| 国产成人精品av在线| 4438全国亚洲精品在线观看视频| 亚洲电影av在线| 日韩亚洲一区二区| 国产丝袜视频一区| 欧美成人自拍视频| 91美女片黄在线观看游戏| 国产精品第一页在线| 欧美精品videos| 法国裸体一区二区| 国产精品久久久久久久久久| 91精品久久久久久久久久久久久久| 91精品国产99久久久久久| 国产精品丝袜视频| 粉嫩老牛aⅴ一区二区三区| 69av视频在线播放|