国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

閉包詳解一

cnio / 2930人閱讀

摘要:再看一段代碼這樣就清晰地展示了閉包的詞法作用域能訪問的作用域將當做一個值返回執行后,將的引用賦值給執行,輸出了變量我們知道通過引用的關系,就是函數本身。

在正式學習閉包之前,請各位同學一定要確保自己對詞法作用域已經非常的熟悉了,如果對詞法作用域還不夠熟悉的話,可以先看:

深入理解閉包之前置知識---作用域與詞法作用域

前言

現在去面試前端開發的崗位,如果你的面試官也是個前端,并且不是太水的話,你有很大的概率會被問到JavaScript中的閉包。因為這個閉包這個知識點真的很重要,還非常難掌握。

什么是閉包

什么是閉包,你可能會搜出很多答案....

《JavaScript高級程序設計》這樣描述:

閉包是指有權訪問另一個函數作用域中的變量的函數;

《JavaScript權威指南》這樣描述:

從技術的角度講,所有的JavaScript函數都是閉包:它們都是對象,它們都關聯到作用域鏈。

《你不知道的JavaScript》這樣描述:

當函數可以記住并訪問所在的詞法作用域時,就產生了閉包,即使函數是在當前詞法作用域之外執行。

我最認同的是《你不知道的JavaScript》中的描述,雖然前面的兩種說法都沒有錯,但閉包應該是基于詞法作用域書寫代碼時產生的自然結果,是一種現象!你也不用為了利用閉包而特意的創建,因為閉包的在你的代碼中隨處可見,只是你還不知道當時你寫的那一段代碼其實就產生了閉包。

講解閉包

上面已經說到,當函數可以記住并訪問所在的詞法作用域時,就產生了閉包,即使函數是在當前詞法作用域之外執行

看一段代碼

function fn1() {
    var name = "iceman";
    function fn2() {
        console.log(name);
    }
    fn2();
}
fn1();

如果是根據《JavaScript高級程序設計》和《JavaScript權威指南》來說,上面的代碼已經產生閉包了。fn2訪問到了fn1的變量,滿足了條件“有權訪問另一個函數作用域中的變量的函數”,fn2本身是個函數,所以滿足了條件“所有的JavaScript函數都是閉包”。

這的確是閉包,但是這種方式定義的閉包不太好觀察。

再看一段代碼:

function fn1() {
    var name = "iceman";
    function fn2() {
        console.log(name);
    }
    return fn2;
}
var fn3 = fn1();
fn3();

這樣就清晰地展示了閉包:

fn2的詞法作用域能訪問fn1的作用域

將fn2當做一個值返回

fn1執行后,將fn2的引用賦值給fn3

執行fn3,輸出了變量name

我們知道通過引用的關系,fn3就是fn2函數本身。執行fn3能正常輸出name,這不就是fn2能記住并訪問它所在的詞法作用域,而且fn2函數的運行還是在當前詞法作用域之外了。

正常來說,當fn1函數執行完畢之后,其作用域是會被銷毀的,然后垃圾回收器會釋放那段內存空間。而閉包卻很神奇的將fn1的作用域存活了下來,fn2依然持有該作用域的引用,這個引用就是閉包

總結:某個函數在定義時的詞法作用域之外的地方被調用,閉包可以使該函數極限訪問定義時的詞法作用域

注意:對函數值的傳遞可以通過其他的方式,并不一定值有返回該函數這一條路,比如可以用回調函數:

function fn1() {
    var name = "iceman";
    function fn2() {
        console.log(name);
    }
    fn3(fn2);
}
function fn3(fn) {
    fn();
}
fn1();

本例中,將內部函數fn2傳遞給fn3,當它在fn3中被運行時,它是可以訪問到name變量的。

所以無論通過哪種方式將內部的函數傳遞到所在的詞法作用域以外,它都回持有對原始作用域的引用,無論在何處執行這個函數都會使用閉包。

再次解釋閉包

以上的例子會讓人覺得有點學院派了,但是閉包絕不僅僅是一個無用的概念,你寫過的代碼當中肯定有閉包的身影,比如類似如下的代碼:

function waitSomeTime(msg, time) {
    setTimeout(function () {
        console.log(msg)
    }, time);
}
waitSomeTime("hello", 1000);

定時器中有一個匿名函數,該匿名函數就有涵蓋waitSomeTime函數作用域的閉包,因此當1秒之后,該匿名函數能輸出msg。

另一個很經典的例子就是for循環中使用定時器延遲打印的問題:

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

在這段代碼中,我們對其的預期是輸出1~10,但卻輸出10次11。這是因為setTimeout中的匿名函數執行的時候,for循環都已經結束了,for循環結束的條件是i大于10,所以當然是輸出10次11咯。

究其原因:i是聲明在全局作用中的,定時器中的匿名函數也是執行在全局作用域中,那當然是每次都輸出11了。

原因知道了,解決起來就簡單了,我們可以讓i在每次迭代的時候,都產生一個私有的作用域,在這個私有的作用域中保存當前i的值。

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

這樣就達到我們的預期了呀,讓我們用一種比較優雅的寫法改造一些,將每次迭代的i作為實參傳遞給自執行函數,自執行函數中用變量去接收:

for (var i = 1; i <= 10; i++) {
    (function (j) {
        setTimeout(function () {
            console.log(j);
        }, 1000);
    })(i);
}
閉包的應用

閉包的應用比較典型是定義模塊,我們將操作函數暴露給外部,而細節隱藏在模塊內部:

function module() {
    var arr = [];
    function add(val) {
        if (typeof val == "number") {
            arr.push(val);
        }
    }
    function get(index) {
        if (index < arr.length) {
            return arr[index]
        } else {
            return null;
        }
    }
    return {
        add: add,
        get: get
    }
}
var mod1 = module();
mod1.add(1);
mod1.add(2);
mod1.add("xxx");
console.log(mod1.get(2));

關于閉包還有很多要講,這里先講解比較基礎的概念,接下來還會有更精彩的內容。

特別注意

可以關注我的公眾號:icemanFE,接下來持續更新技術文章!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95273.html

相關文章

  • 詳解js閉包

    摘要:但閉包的情況不同嵌套函數的閉包執行后,,然后還在被回收閉包會使變量始終保存在內存中,如果不當使用會增大內存消耗。每個函數,不論多深,都可以認為是全局的子作用域,可以理解為閉包。 閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高級應用都要依靠閉包實現。 閉包的特性 閉包有三個特性: 1.函數嵌套函數 2.函數內部可以引用外部的參數和變量 3.參數和變量不會...

    Chiclaim 評論0 收藏0
  • Javascript 閉包詳解

    摘要:一般函數執行完畢,局部活動對象就會被銷毀,內存中僅僅保存全局作用域,但是閉包會長期駐扎在內存。我只是想通過這兩個例子來說明閉包的用處和好處。閉包會使變量始終保存在內存中,如果使用不當會增大內存消耗。 閉包特性 函數嵌套函數 函數內部可以引用外部的參數和變量 參數和變量不會被垃圾回收機制回收 閉包的作用 具體作用是有權訪問函數內部的變量,最常見的就是函數內部創建另一個函數,通過另一個函數...

    ztyzz 評論0 收藏0
  • 詳解js中的閉包

    摘要:定義函數的時候,為什么的值重新從開始了因為又一次運行了函數,生成一個新的的活動對象,所以的作用域鏈引用的是一個新的值。 前言 在js中,閉包是一個很重要又相當不容易完全理解的要點,網上關于講解閉包的文章非常多,但是并不是非常容易讀懂,在這里以《javascript高級程序設計》里面的理論為基礎。用拆分的方式,深入講解一下對于閉包的理解,如果有不對請指正。 寫在閉包之前 閉包的內部細節,...

    chaosx110 評論0 收藏0
  • 閉包全面詳解

    摘要:環境由閉包創建時在作用域中的任何局部變量組成。嚴格來說,閉包需要滿足三個條件訪問所在作用域函數嵌套在所在作用域外被調用閉包的形成原理先了解的垃圾回收機制會找出不再使用的變量,不再使用意味著這個變量生命周期的結束。 什么是閉包 最原始定義 閉包(closure),是指函數變量可以保存在函數作用域內,因此看起來是函數將變量包裹了起來。 //根據定義,包含變量的函數就是閉包 function...

    qylost 評論0 收藏0
  • ES5和ES6數組遍歷方法詳解

    摘要:和數組遍歷方法詳解在中常用的種數組遍歷方法原始的循環語句數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法數組對象內置方法循環語句中新增加了一種循環語句三種數組循環示例如下原始循 ES5和ES6數組遍歷方法詳解 在ES5中常用的10種數組遍歷方法: 1、原始的for循環語句2、Array.prototype.forEach數...

    GitChat 評論0 收藏0

發表評論

0條評論

cnio

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<