中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中的閉包是怎樣的

發布時間:2021-12-18 18:00:51 來源:億速云 閱讀:114 作者:柒染 欄目:開發技術

這篇文章給大家介紹JavaScript中的閉包是怎樣的,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

    1. 閉包的概念

    來看一般函數的執行和啟發:

    function stop() {
                var num = 0;
                console.log(num);
            }
            stop(); // 打印出來num是0
            console.log(num); // 報錯 函數未定義

    1. 此時,函數的外部無法訪問函數內部的變量

    2. 函數內部定義的變量不會一直存在,隨著函數的運行結束而消失

    閉包的概念:

    1. 是一個函數,這個函數有權訪問另一個作用域中的變量。

    2. 另一種說法,當內部函數的生命周期大于外部函數的聲明周期,而內部函數以某一種方式被外部作用域訪問時,閉包就產生了。

    來看如下閉包的代碼和解釋:

    function fn() {
                var num = 10;
                // function fun() {
                //     console.log(num);
     
                // }
                // return fun;
                return function () {
                    console.log(num); // 10
                }
            }
            var f = fn();
            f();

    我們可以拆解為幾個部分:

    1. fn函數里面有內部的返回值且就是一個函數。

    2. return的這個函數內部打印了num變量。為什么能夠打印num變量,原因在于作用域鏈的訪問機制,下面會補充作用域和作用域鏈的知識點。

    3. 我們在外部用f變量接受了fn(),也就是接受了fn的返回值【內部函數】

    4. 緊接著調用f,也就是調用了fn里面的內部函數。最終能夠打印10

    知識點的補充:

    1. 作用域:

    變量在某個范圍內起作用,超出了這個范圍,就不起作用。這個范圍就是作用域。作用域在函數的定義時就產生,而不是函數調用時產生的。

    2. 作用域鏈:

    一句話概括:根據【內部函數可以訪問外部函數變量】,采用就近原則一層一層向上查找變量,這個機制就叫作作用域鏈。

    函數A包含了函數B,那么函數B就是函數A的內部函數,

    而內部函數如果要使用一個變量,首先看自己內部有沒有這個變量,

    如果沒有,就會去緊挨著的上一級查找,【就近原則】

    如果函數一層一層都找不到,最后才會去全局變量下面找。

    var a = 1;
            var b = 11;
            function fn1() {
                var a = 2;
                var b = '22';
                fn2();
                function fn2() {
                    var a = 3;
                    fn3();
                    function fn3() {
                        var a = 4;
                        console.log(a); // 4
                        console.log(b); // '22'
                    }
                }
            }
            fn1();

    3. 垃圾回收機制

    可以參考這位大哥對于JS垃圾回收機制的描述:

    //www.5655pk.com/article/229425.htm

    我們結合這三個概念看閉包的作用

    2. 閉包的作用:

    我們把函數A叫作外層的函數,這個函數內部有一個函數B。

    外部用一個變量f接受函數A的返回值【函數B】

    而函數A作用域的變量叫作num

    1. 能夠在函數的外部訪問函數內部的變量【搭建外部訪問內部作用域的通道】

    原理:上面其實有解釋過。

    第一要理解,作用鏈的原理看上面。函數B能夠調用函數A的變量num

    第二要理解,首先函數A的返回值是函數B【內部函數】,其次這個返回值要在函數外部用變量f接受,接受以后就能夠調用函數B,函數B就會訪問函數A的變量num。而這個內部函數B就是閉包函數啦。

    2. 能夠延長函數內部變量的生命周期。

    第一個作用帶來第二個作用。js的變量存在垃圾回收機制,如果函數執行完畢,變量會被清除,內存也會消除。可是如果利用閉包,變量可以不被立即清除。

    原因是,外部的變量f接受了一個函數A的內部函數B,而這個內部函數訪問了函數A作用域的變量num,只要函數B執行且變量f一直存在,那么變量num就會一直存在。不會因為函數A的執行結束就消失。

    參考了下面的文章,講的非常詳細,推薦看。

    JavaScript閉包詳解

    3. 閉包示例

    后面會補充閉包的一些應用。

    我們要想起什么場合用閉包,閉包不能濫用。

    3.1 點擊li,輸出當前li的索引號

    <ul class="nav">
            <li>榴蓮</li>
            <li>臭豆腐</li>
            <li>鯡魚罐頭</li>
            <li>大豬蹄子</li>
        </ul>
        <script>
            // 閉包應用-點擊li輸出當前li的索引號
            // 1. 我們可以利用動態添加屬性的方式
            var lis = document.querySelector('.nav').querySelectorAll('li');
            for (var i = 0; i < lis.length; i++) {
                lis[i].onclick = function () {
                    console.log(i); // 四個4
                }
            }
        </script>

    原理:上圖這樣寫,打印出來的i永遠都是4。原因是,此時首先是非嚴格模式,在非嚴格模式下,for循環是同步執行任務,而按鈕點擊再執行是異步任務,同步執行完畢,i加到了4.再執行異步任務打印i,都是4。

    改法1:用閉包

    1.for循環生成四個立即執行函數

    2. 立即執行函數是閉包的一種應用。立即執行函數里面的所有函數包括【點擊 回調】函數都可以使用立即執行函數的傳遞的形參。

    for (var i = 0; i < lis.length; i++) {
                (function (i) {
                    // console.log(i);
                    lis[i].onclick = function () {
                        console.log(i);
     
                    }
                })(i);
            }

    改法2:var--->let

    點擊對應小li,打印i是對應索引號。使用let是ES6語法,此時for有塊級作用域

    var lis = document.querySelector('.nav').querySelectorAll('li');
            for (let i = 0; i < lis.length; i++) {
                lis[i].onclick = function () {
                    // console.log(i);
                    console.log(i);
                }
            }

    改法3:用設置自定義屬性index的方法

    var lis = document.querySelector('.nav').querySelectorAll('li');
            for (var i = 0; i < lis.length; i++) { // 注意這里是var不是let
                lis[i].index = i; // 注意這里是lis[i]不是this.index,此時沒有點擊,哪里來的this
                lis[i].onclick = function () {
                    console.log(this.index);
                }
            }

    關于JavaScript中的閉包是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    青铜峡市| 饶阳县| 蕉岭县| 合川市| 克拉玛依市| 五峰| 龙山县| 绥芬河市| 天镇县| 江津市| 银川市| 杭州市| 丁青县| 紫云| 盖州市| 太康县| 尼玛县| 乌鲁木齐县| 濉溪县| 揭东县| 阳朔县| 沈丘县| 远安县| 莱州市| 山东省| 满城县| 大荔县| 香港| 梁河县| 通江县| 华池县| 临清市| 肥乡县| 中宁县| 南平市| 达尔| 怀宁县| 积石山| 神池县| 钟祥市| 高清|