最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaScript中的閉包是如何產(chǎn)生的

 更新時間:2022年12月28日 10:43:04   作者:前端西瓜哥  
這篇文章主要為大家詳細介紹了從內(nèi)存管理的角度來看,JavaScript中的閉包是如何產(chǎn)生的。文中的示例代碼簡潔易懂,感興趣的小伙伴可以了解一下

這次從內(nèi)存管理的角度來看看,閉包是怎么產(chǎn)生的。

我們知道,在調(diào)用函數(shù)時,其實會產(chǎn)生臨時的 調(diào)用棧。這些調(diào)用棧保存的是 執(zhí)行上下本,并實際保存在 棧內(nèi)存 中。

每執(zhí)行一個函數(shù),函數(shù)內(nèi)的局部臨時變量會臨時保存起來。如果此時函數(shù)又調(diào)用了另一個函數(shù),另一個函數(shù)下的局部變量也要保存下來,就這樣,我們產(chǎn)生了棧。

當一個函數(shù)執(zhí)行完后,它對應的局部臨時變量就會被銷毀。

局部變量保存下來,是為了保護上下文現(xiàn)場。

舉例說明一下:

function a() {
  const a_num = 99;
  const a_obj = { val: "a" };
  b();
}

function b() {
  const b_str = "text";
  c();
}

function c() {
  const c_bool = true;
  // debugger
}

a();

這里我們嵌套調(diào)用了 a、b、c 函數(shù),會產(chǎn)生如下的調(diào)用棧。

基本類型的臨時變量,會直接保存到棧內(nèi)存中,對于引用類型,則是在堆內(nèi)存中生成,然后將地址拿到,保存到棧內(nèi)存中。

引用類型為什么不直接放到棧內(nèi)存中?因為棧內(nèi)存不是很大,很容易就棧溢出,而引用類型通常很大。

閉包的產(chǎn)生

函數(shù)調(diào)用完成后,它內(nèi)部聲明的臨時變量會被銷毀。理論上應該如此,但如果使用了閉包,可以會讓臨時變量一直保留不被銷毀。

例子:

function createCounter() {
  let count = 0;
  let otherVal = "other val";
  return function counter() {
    // debugger;
    console.log(count++);
  };
}

const counter = createCounter();

console.log(counter());

執(zhí)行過程為:

  • 執(zhí)行函數(shù) createCounter 時,會創(chuàng)建一個空的上下文對象。
  • 遇到內(nèi)部函數(shù) counter,會 預掃描內(nèi)部函數(shù) counter 使用了 createCounter 下的哪些便利,最終掃描出 count 變量。于是在堆內(nèi)存創(chuàng)建一個閉包 Closure (createCounter) 對象,將 count 加進去。otherVal 不會加到閉包對象上,因為它沒有被使用。
  • 這個內(nèi)部函數(shù)最后被返回,被引用,閉包就一直不會銷毀。

使用 DevTool 可以觀察到這個閉包對象:

所以,如果一個閉包返回的函數(shù)執(zhí)行完后不用了,要設置為 null。否則它關聯(lián)的閉包對象會一直在那里占用內(nèi)存。

多個內(nèi)部函數(shù)共享一個閉包對象

另外,如果有多個內(nèi)部函數(shù),這些函數(shù)會共用同一個閉包對象。即使其中的一個內(nèi)部函數(shù)不會返回,它也會給閉包對象加東西。

下面我們加了一個 printOtherVal 的內(nèi)部函數(shù),它并不返回,但還是會導致返回 counter 函數(shù)對應的閉包對象帶上了它不需要的 otherVal 變量。

這是 JS 引擎處理閉包策略問題,理論不應該有這樣奇怪的效果。

結尾

調(diào)用函數(shù)時,會產(chǎn)生調(diào)用棧,將當前函數(shù)上下文入棧,會保存基本類型變量。引用變量會在堆內(nèi)存中創(chuàng)建,然后在棧內(nèi)存中引用過來。

因為 JavaScript 中函數(shù)是第一公民,所以會有閉包的概念。當發(fā)現(xiàn)內(nèi)部函數(shù),會創(chuàng)建一個閉包對象,將其中使用到的外部函數(shù)變量保存到該閉包對象下。之后內(nèi)部函數(shù)被調(diào)用時,就會從閉包里提取變量,如果找不到則從全局上下文提取。

到此這篇關于詳解JavaScript中的閉包是如何產(chǎn)生的的文章就介紹到這了,更多相關JavaScript閉包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JS實現(xiàn)可移動模態(tài)框

    JS實現(xiàn)可移動模態(tài)框

    這篇文章主要為大家詳細介紹了JS實現(xiàn)可移動模態(tài)框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • JS原型鏈 詳解及示例代碼

    JS原型鏈 詳解及示例代碼

    本文主要介紹JS原型鏈的知識,這里整理了相關資料及簡單實現(xiàn)示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • 理解javascript定時器中的setTimeout與setInterval

    理解javascript定時器中的setTimeout與setInterval

    這篇文章主要幫助大家學習理解javascript定時器中的setTimeout與setInterval,從實例出發(fā)進行深入探討,感興趣的小伙伴們可以參考一下
    2016-02-02
  • javascript 初學教程及五子棋小程序的簡單實現(xiàn)

    javascript 初學教程及五子棋小程序的簡單實現(xiàn)

    下面小編就為大家?guī)硪黄猨avascript 初學教程及五子棋小程序的簡單實現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • echart簡介_動力節(jié)點Java學院整理

    echart簡介_動力節(jié)點Java學院整理

    這篇文章主要介紹了echart簡介,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • TypeScript 泛型的使用

    TypeScript 泛型的使用

    這篇文章主要介紹了TypeScript 泛型的使用,在JavaScript中,封裝一個API可以具有多種用途,因為其實弱類型語言,但是就因為是弱類型可以最終得到的結果并不是我們想要的,下面我們就來看看具體TypeScript 泛型的使用吧
    2021-12-12
  • JS+JSP checkBox 全選具體實現(xiàn)

    JS+JSP checkBox 全選具體實現(xiàn)

    本文為大家介紹下使用JS+JSP實現(xiàn)checkBox全選,下面有個不錯的示例,感興趣的朋友可以參考下
    2014-01-01
  • 使用JS+XML(數(shù)據(jù)島)實現(xiàn)分頁)

    使用JS+XML(數(shù)據(jù)島)實現(xiàn)分頁)

    使用JS+XML(數(shù)據(jù)島)實現(xiàn)分頁)...
    2007-01-01
  • 常用DOM整理

    常用DOM整理

    js在操作DOM中存在著許多跨瀏覽器方面的坑,本文花了我將近一周的時間整理,我將根據(jù)實例整理那些大大小小的“坑”。
    2015-06-06
  • javascript實現(xiàn)的文字加密解密

    javascript實現(xiàn)的文字加密解密

    javascript實現(xiàn)的文字加密解密...
    2007-06-06

最新評論

璧山县| 涿州市| 沁水县| 舒城县| 搜索| 囊谦县| 杂多县| 岚皋县| 余江县| 昌乐县| 图们市| 海口市| 永州市| 洞口县| 金华市| 南通市| 新平| 额敏县| 攀枝花市| 名山县| 阳谷县| 鄂托克前旗| 太湖县| 图片| 凌源市| 大港区| 巢湖市| 类乌齐县| 陆丰市| 逊克县| 息烽县| 乌兰察布市| 花莲县| 松阳县| 西青区| 伊宁县| 新平| 莱西市| 孙吴县| 怀集县| 三原县|