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

資訊專欄INFORMATION COLUMN

圖解JS閉包形成的原因

wind3110991 / 2694人閱讀

摘要:閉包的出現正好結合了全局變量和局部變量的優點。這就是閉包的一個使用場景保存現場。

前言

什么是閉包,其實閉包是可以重用一個對象,又保護對象不被篡改的一種機制。什么是重用一個對象又保護其不被篡改呢?請看下面的詳解。

作用域和作用域鏈

注意
理解作用域和作用域鏈對理解閉包有非常大的幫助,所以我們先說一下作用域和作用域鏈

什么是作用域
作用域表示的是一個變量的可用范圍、其實它是一個保存變量的對象
為什么要使用作用域
避免不同范圍的變量互相干擾

作用域包含了哪兩種
1、全局作用域
在JavaScript中的全局作用域其實就是windows
優點:可重復使用,隨處可用
缺點:會造成全局污染

2、函數作用域
臨時創建的活動對象AO(Activation Object)、該對象包含了函數的所有局部變量、命名參數、參數集合以及this,當運行時上下文被銷毀、活動也會被銷毀(閉包形成的原因其實因為就是因為活動對象被引用著無法被銷毀而導致的,詳細的請繼續往下看)
優點:不污染全局
缺點:不可重復使用、僅在函數內可以使用

程序執行的四個階段
我以下面一段代碼解釋一下程序執行的幾個階段

    var age = "21";
    function myAge(){
        var age = 0;
        age++;
        console.log(age);
    }
    myAge();
    console.log(age);

第一階段:在內存中創建執行執行環境棧、把全局對象window壓入棧底、在window中聲明變量

第二階段:函數調用時
在執行環境中添加當前函數調用、為本次函數調用創建活動對象AO、根據scope指定運行期活動對象AO的上下文內部對象

第三階段:函數調用后
函數調用從執行環境棧中出棧、函數作用域AO釋放、函數作用域AO中的局部變量也一同被釋放

由上面可以看出當一個函數調用完畢它的局部變量就會被釋放,下次再次調用時會創建新的局部變量。這就是函數中的局部變量不可重用的原因。

為什么要使用閉包

先介紹一下全局變量和局部變量的優缺點
全局變量:可以重用、但是會造成全局污染而且容易被篡改
局部變量:僅函數內使用不會造成全局污染也不會被篡改、不可以重用
從上面可以看出全局變量和局部變量的優缺點剛好是相對的。閉包的出現正好結合了全局變量和局部變量的優點。

何時使用閉包
希望重用一個對象,又保護對象不被污染篡改時

閉包的實現原理

弄清楚了作用域和作用域鏈、閉包實現的原理也就很容易弄懂了。
下面請看一段代碼和幾張圖^_^
這是一段閉包的代碼,我們又這段代碼講講閉包的原理

    function addAge(){
        var age = 21;
        return function(){
            age++;
            console.log(age);
        }
    }
    var clourse = addAge();
    clourse();
    clourse();
    clourse();

第一階段:在內存中創建執行執行環境棧、把全局對象window壓入棧底、在window中聲明變量(和前面是相似的)

第二階段:
1、在棧中添加addAge的函數調用
2、為addAge函數創建活動對象AO、根據addAge函數的scope可以知道其活動對象指向window
3、window對象中的clourse變量記錄著addAge()返回的匿名函數的地址[現在addAge()和clourse變量都可以找到匿名函數和addAge()產生的AO]

第三階段:
addAge()調用完畢出棧、其對活動對象AO的引用也隨之消失。
在作用域和作用域鏈中舉的例子中,活動對象AO會被JS中的垃圾回收機制回收大家還記得嘛^_^,
但是這里和前面是不一樣的哦!注意了:匿名函數中的scope引用著活動對象AO、匿名函數的地址也被clourse變量記錄著。因此,addAge()雖然出棧了,對它的活動對象的引用也消失了,但是其活動對象被匿名函數的scope拽著、所以無法釋放不會被回收。
大家觀看藍色的箭頭,其實可以發現、藍色的箭頭已經形成了一個閉環了。
此時,由圖也可以看出,活動對象AO只能通過clourse變量來找到。這里形成了一個閉包。保存了addAge()函數中的局部變量,使其可以重復使用,但是又不會造成全局污染。這就是閉包的一個使用場景:保存現場。
至于怎么調用重復使用局部變量,具體過程請看下面兩幅圖。

第四階段:
clourse()進棧,產生clouse()的活動對象AO,根據它的scope可以知道它的__parent__指向addAge()產生的活動對象AO。
clouse()執行age++,由于在它自己的作用域里面沒有age、于是它會到上一級作用域查找age,它在它的上一級作用域中找到了age,于是對其進行了age++,age從21變成了22。執行console.log(age)輸出22。

第五階段:
clourse()出棧,因為clourse產生的AO沒有scope拽著它,因此clourse的AO是可以正常釋放的。函數出棧,其AO被JS的垃圾回收機制回收。
clourse變量中的匿名函數中的scope依舊拽著addAge()產生的活動對象AO,于是這個活動對象依舊無法被釋放[而且這個AO現在只能被clourse找到、clourse可以重復使用這個AO里面的局部變量age、又不會造成全局污染]

剩下階段:
代碼中還有兩個函數還有執行

clourse()
clourse()

它的執行和第四階段和第五階段的原理是一樣的。所以在這里我就不重復畫圖了。
執行clourse():看第四階段的圖,age從22變成了23,執行console.log(age)輸出23、看第五階段的圖
執行clourse(): 看第四階段的圖,age從23變成了24,執行console.log(age)輸出24、看第五階段的圖

總結

以上就是對閉包形成過程的圖解。也說明了閉包保存現場的作用場景。閉包結合了局部變量和全局變量的優點??梢允棺兞坎晃廴救郑怯帜軐ψ兞窟M行重用。但是,其實閉包也有有缺點的,它比起普通函數會占用更多的內存。
總的來說,以上就是我對閉包的理解。如果大家發現了什么錯誤歡迎評論指出,一起交流一起學習一起進步!^_^

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

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

相關文章

  • 結合作用域,執行上下文圖解閉包

    摘要:作用域鏈所謂作用域鏈,是由當前環境與上層環境的一系列變量對象組成,它保證當前執行環境對符合訪問權限的變量和函數的有序訪問。當我們在執行函數的時候,需要的變量,在自己的作用域內找不到,便會順著作用域鏈往上找,直到找到全局作用域。 一 作用域相關? ? ? 作用域是一套規則,用來管理引擎如何查找變量。在es5之前,js只有全局作用域及函數作用域。es6引入了塊級作用域。但是這個塊級別作用域...

    msup 評論0 收藏0
  • 圖解作用域及閉包

    摘要:那其實閉包的原因就是外層函數的作用域對象無法釋放其實就是一個函數調用會生成的臨時作用域圖中可看出其實就是在中的匿名函數,所以他的就指向留下的作用域。 引言 網絡上關于作用域及閉包的文章很多,自己對于純理論知識并不能很快的理解,但自己對于圖畫有很強的記憶和理解能力,因此決定將此知識點以圖畫的知識表現出來,加深自身理解的同時如果能幫到正在學習的童鞋就再好不過了 下面我以函數的整個生命周期來...

    shiyang6017 評論0 收藏0
  • 理解閉包

    摘要:我的理解就是還處于被引用狀態。內存機制的內存空間分為棧堆其中棧存放變量,堆存放復雜對象。對堆內數據進行復制修改時理解閉包有了前面的鋪墊,我們再來看看閉包是怎么回事。這種反常的現象我們就叫它,中文名閉包。這就是閉包形成的原因了。 知識小儲備 ECMAScript 的數據有兩種類型:基本類型值和引用類型值,基本類型指的是簡單的數據段,引用類型指的是可能由多個值構成的對象。Undefined...

    fox_soyoung 評論0 收藏0
  • javascript系列--javascript深入淺出圖解作用域鏈和閉包

    摘要:變量對象也是有父作用域的。作用域鏈的頂端是全局對象。當函數被調用的時候,作用域鏈就會包含多個作用域對象。當函數要訪問時,沒有找到,于是沿著作用域鏈向上查找,在的作用域找到了對應的標示符,就會修改的值。 一、概要 對于閉包的定義(紅寶書P178):閉包就是指有權訪問另外一個函數的作用域中的變量的函數。 關鍵點: 1、閉包是一個函數 2、能夠訪問另外一個函數作用域中的變量 二、閉包特性 對...

    Jensen 評論0 收藏0
  • 《javascript高級程序設計》筆記:內存與執行環境

    摘要:因此,所有在方法中定義的變量都是放在棧內存中的當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復利用因為對象的創建成本通常較大,這個運行時數據區就是堆內存。 上一篇:《javascript高級程序設計》筆記:繼承近幾篇博客都會圍繞著圖中的知識點展開 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...

    fuyi501 評論0 收藏0

發表評論

0條評論

wind3110991

|高級講師

TA的文章

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