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

資訊專欄INFORMATION COLUMN

圖解作用域及閉包

shiyang6017 / 2052人閱讀

摘要:那其實(shí)閉包的原因就是外層函數(shù)的作用域?qū)ο鬅o法釋放其實(shí)就是一個(gè)函數(shù)調(diào)用會(huì)生成的臨時(shí)作用域圖中可看出其實(shí)就是在中的匿名函數(shù),所以他的就指向留下的作用域。

引言

網(wǎng)絡(luò)上關(guān)于作用域及閉包的文章很多,自己對(duì)于純理論知識(shí)并不能很快的理解,但自己對(duì)于圖畫有很強(qiáng)的記憶和理解能力,因此決定將此知識(shí)點(diǎn)以圖畫的知識(shí)表現(xiàn)出來,加深自身理解的同時(shí)如果能幫到正在學(xué)習(xí)的童鞋就再好不過了

下面我以函數(shù)的整個(gè)生命周期來訴說此部分知識(shí)

函數(shù)生命周期

先寫一下示例代碼

var a = 10;
function func(a) {
  var a = 20;
  a++;
  console.log(a);
}
func();
console.log(a);
開始執(zhí)行程序前

先創(chuàng)建 ECS,ECS 其實(shí)就是專門保存正在調(diào)用的函數(shù)的執(zhí)行環(huán)境的數(shù)組,也可以說對(duì)象,其實(shí)關(guān)聯(lián)數(shù)組也就相當(dāng)于對(duì)象。

然后在 ECS 中添加瀏覽器主程序的執(zhí)行環(huán)境 main

創(chuàng)建全局作用域?qū)ο?window

main 執(zhí)行環(huán)境引用 window

定義函數(shù)時(shí)

原始類型的全局變量會(huì)直接存入 window 環(huán)境當(dāng)中,因?yàn)楹瘮?shù)是引用類型,所以首先用函數(shù)名聲明全局變量

然后創(chuàng)建函數(shù)對(duì)象,封裝函數(shù)定義

函數(shù)對(duì)象的 scope 屬性,指回函數(shù)創(chuàng)建時(shí)的作用域,意思是,函數(shù)執(zhí)行時(shí)如果函數(shù)本身提供的變量不能讓函數(shù)執(zhí)行完全,那它便會(huì)去回它創(chuàng)建時(shí)的那個(gè)作用域去尋找變量。

函數(shù)名后面存入指向函數(shù)對(duì)象的地址

引用類型在其中只能存儲(chǔ)地址,這個(gè)在此筆記談?wù)勚祩鬟f中有詳細(xì)說明

函數(shù)調(diào)用時(shí)

向 ECS 中壓入本次函數(shù)調(diào)用的執(zhí)行環(huán)境元素

創(chuàng)建本次函數(shù)調(diào)用時(shí)使用的函數(shù)作用域?qū)ο螅ˋO),也就是臨時(shí)作用域

在 AO 中創(chuàng)建儲(chǔ)存所有的局部變量,包括形參變量和函數(shù)內(nèi)用 var 聲明的變量

設(shè)置 AO 的 parent 屬性和引用函數(shù)的 scope 屬性指向父級(jí)作用域?qū)ο?/p>

函數(shù)的執(zhí)行環(huán)境引用 AO

順著那個(gè)箭頭,先在 AO 中找變量,也就是局部變量,如果 AO 中沒有,再順著箭頭去父級(jí)作用域中找

函數(shù)調(diào)用后

函數(shù)的執(zhí)行環(huán)境出棧,AO 釋放,AO 中的局部變量一同被釋放掉。

我們得知整個(gè)結(jié)果之后,自然而然那兩個(gè) console 的結(jié)果也顯然意見。

閉包

前面我們提到過,全局變量是可重用但是污染全局,局部變量不會(huì)污染全局但是不可重用。

我自己認(rèn)為閉包就是重用變量又保護(hù)變量不被污染的機(jī)制,就是為了解決這一情況而生的。

特點(diǎn)

包裹受保護(hù)的變量和操作變量的內(nèi)層函數(shù)的外層函數(shù)

外層函數(shù)要返回內(nèi)層函數(shù)的對(duì)象

return function(){..}

直接給全局變量賦值一個(gè)內(nèi)部 function

將內(nèi)部函數(shù)保存在一個(gè)對(duì)象的屬性或數(shù)組元素中 return [function function function]return {fun:function(){...}}

調(diào)用外層函數(shù),用外部變量接住返回的內(nèi)層函數(shù)對(duì)象,形成閉包。

原理

先貼出示例代碼

function outer() {
  var num = 1;
  return function() {
    console.log(num++);
  };
}

var getNum = outer();
getNum();
getNum();
num = 1;
getNum();

下面我把閉包形成的原理用畫圖工具畫出來

window 中存入 outer 名并指向 outer 函數(shù)對(duì)象,getNum 因?yàn)槁暶魈崆耙蚕葘⒆兞棵嬖?window 中。

getNum = outer() 其實(shí)包含 outer 的創(chuàng)建和 getNum 的賦值。

上面的圖畫的是 outer 函數(shù)進(jìn)行到 var num = 1; ,前面都有說過,不過多重復(fù)。

創(chuàng)建了匿名函數(shù),getNum 指向了匿名函數(shù)對(duì)象,匿名對(duì)象的 scope 指向它的父級(jí)作用域,也就是 outer 的作用域,那這樣就形成了圖中的三角關(guān)系,此時(shí) outer 執(zhí)行完畢,離開 ECS 執(zhí)行環(huán)境,outer 的 AO 本也應(yīng)該隨著離開,但是因?yàn)檫@強(qiáng)大的三角關(guān)系,強(qiáng)行拉住不讓其釋放,也就形成了所謂的閉包。

那其實(shí)閉包的原因就是:外層函數(shù)的作用域?qū)ο鬅o法釋放

getNum=outer()getNum 其實(shí)就是一個(gè)函數(shù)

調(diào)用getNum(),會(huì)生成 getNum 的臨時(shí)作用域,圖中可看出,getNum 其實(shí)就是在 outer 中的匿名函數(shù),所以他的 parent 就指向 outer 留下的作用域。當(dāng)他執(zhí)行 console.log(num++) 的時(shí)候,在他的作用域中沒有 num 變量他就會(huì)順著作用域鏈去尋找,最終在 outer 中的作用域中找到 num 并對(duì)其進(jìn)行自加操作。所以當(dāng)下次調(diào)用 getNum 的時(shí)候 num 會(huì)從 2 開始,不會(huì)是一開始的 1

num 不是全局變量,還實(shí)現(xiàn)了 num 變量的重復(fù)調(diào)用。就達(dá)到了閉包的目的。

設(shè)置 num = 1 只是在 window 對(duì)象上添加存儲(chǔ) num 的值,當(dāng)下次調(diào)用 getNum 的時(shí)候 js 引擎還會(huì)從 getNum 作用域開始順著作用域鏈尋找 num,在 outerAO 就會(huì)尋找到 num,所以根本不會(huì)影響到 window 中的 num,也不會(huì)受其影響。因此此段代碼輸出的結(jié)果為 1 2 3

缺點(diǎn)

當(dāng)然閉包也有其缺點(diǎn)

比普通函數(shù)占用更多內(nèi)存,因?yàn)橥鈱雍瘮?shù)的作用域?qū)ο螅ˋO)始終存在

容易造成內(nèi)存泄漏

解決辦法

將引用內(nèi)存函數(shù)對(duì)象的外部變量重置為 null

getNum = null;

getNum 指向 outer 函數(shù)對(duì)象的那根線就會(huì)斷掉,三角關(guān)系破裂,那函數(shù)對(duì)象和 outerAO 也會(huì)相繼被銷毀。

覺得文章不錯(cuò)的話還請(qǐng)各位大佬給個(gè) star 鼓勵(lì)一下 gayhub

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/94802.html

相關(guān)文章

  • javascript系列--javascript深入淺出圖解作用域鏈和閉包

    摘要:變量對(duì)象也是有父作用域的。作用域鏈的頂端是全局對(duì)象。當(dāng)函數(shù)被調(diào)用的時(shí)候,作用域鏈就會(huì)包含多個(gè)作用域?qū)ο蟆.?dāng)函數(shù)要訪問時(shí),沒有找到,于是沿著作用域鏈向上查找,在的作用域找到了對(duì)應(yīng)的標(biāo)示符,就會(huì)修改的值。 一、概要 對(duì)于閉包的定義(紅寶書P178):閉包就是指有權(quán)訪問另外一個(gè)函數(shù)的作用域中的變量的函數(shù)。 關(guān)鍵點(diǎn): 1、閉包是一個(gè)函數(shù) 2、能夠訪問另外一個(gè)函數(shù)作用域中的變量 二、閉包特性 對(duì)...

    Jensen 評(píng)論0 收藏0
  • 結(jié)合作用域,執(zhí)行上下文圖解閉包

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

    msup 評(píng)論0 收藏0
  • 淺談Javascript閉包作用域及內(nèi)存泄漏問題

    摘要:將作用域賦值給變量這里的作用域是,而不是將作用域賦值給一個(gè)變量閉包返回瀏覽器中內(nèi)存泄漏問題大家都知道,閉包會(huì)使變量駐留在內(nèi)存中,這也就導(dǎo)致了內(nèi)存泄漏。 上一章我們講了匿名函數(shù)和閉包,這次我們來談?wù)勯]包中作用域this的問題。 大家都知道,this對(duì)象是在運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的,如果this在全局就是[object window],如果在對(duì)象內(nèi)部就是指向這個(gè)對(duì)象,而閉包卻是在運(yùn)行...

    source 評(píng)論0 收藏0
  • 《你不知道的JS》讀書筆記---作用域及閉包

    摘要:注此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀你不知道的后的理解。作用域及閉包基礎(chǔ),代碼運(yùn)行的幕后工作者引擎及編譯器。 注:此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀《你不知道的JS》后的理解。 作用域及閉包基礎(chǔ),JS代碼運(yùn)行的幕后工作者:引擎及編譯器。引擎負(fù)責(zé)JS程序的編譯及執(zhí)行,編譯器負(fù)責(zé)詞法分析和代碼生成。那么作用域就像一個(gè)容器,引擎及編譯器都從這里提取東西。 ...

    denson 評(píng)論0 收藏0
  • 詳解js變量、作用域及內(nèi)存

    摘要:不是引用類型,無法輸出簡而言之,堆內(nèi)存存放引用值,棧內(nèi)存存放固定類型值。變量的查詢在變量的查詢中,訪問局部變量要比全局變量來得快,因此不需要向上搜索作用域鏈。 贊助我以寫出更好的文章,give me a cup of coffee? 2017最新最全前端面試題 基本類型值有:undefined,NUll,Boolean,Number和String,這些類型分別在內(nèi)存中占有固定的大小空...

    waltr 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<