成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

閉包是如何產生的?你知道嗎?

開發 前端
調用函數時,會產生調用棧,將當前函數上下文入棧,會保存基本類型變量。引用變量會在堆內存中創建,然后在棧內存中引用過來。

大家好,我是前端西瓜哥。

這次從內存管理的角度來看看,閉包是怎么產生的。

我們知道,在調用函數時,其實會產生臨時的 調用棧。這些調用棧保存的是 執行上下本,并實際保存在 棧內存 中。

每執行一個函數,函數內的局部臨時變量會臨時保存起來。如果此時函數又調用了另一個函數,另一個函數下的局部變量也要保存下來,就這樣,我們產生了棧。

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

局部變量保存下來,是為了保護上下文現場。

舉例說明一下:

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();

這里我們嵌套調用了 a、b、c 函數,會產生如下的調用棧。

圖片

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

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

閉包的產生

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

例子:

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

const counter = createCounter();

console.log(counter());

執行過程為:

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

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

圖片

所以,如果一個閉包返回的函數執行完后不用了,要設置為 null。否則它關聯的閉包對象會一直在那里占用內存。

多個內部函數共享一個閉包對象

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

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

圖片

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

結尾

調用函數時,會產生調用棧,將當前函數上下文入棧,會保存基本類型變量。引用變量會在堆內存中創建,然后在棧內存中引用過來。

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

責任編輯:姜華 來源: 前端西瓜哥
相關推薦

2024-11-26 00:45:29

free區域字段

2024-06-20 08:06:30

2025-01-16 16:41:00

ObjectConditionJDK

2024-10-05 00:00:00

HTTPS性能HTTP/2

2024-10-24 08:47:12

2023-12-20 08:23:53

NIO組件非阻塞

2023-05-30 08:19:07

kafka集群leader

2024-12-04 08:40:19

2022-11-28 00:04:17

2024-01-15 12:16:37

2024-02-19 00:00:00

Docker輕量級容器

2024-07-30 08:22:47

API前端網關

2024-11-08 09:48:38

異步編程I/O密集

2024-07-08 00:00:01

多線程ThreadC#

2023-03-21 07:39:51

CentOS掛載硬盤

2023-01-13 17:02:10

操作系統鴻蒙

2024-02-19 07:44:52

虛擬機Java平臺

2024-03-19 08:01:54

服務熔斷軟件設計模式微服務

2022-11-23 10:33:42

2025-06-27 09:32:47

GoRedis單線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 福利视频网址 | 国产97在线看| 午夜精品一区二区三区免费视频 | 日本精品一区二区三区在线观看视频 | 一区二区三区在线免费看 | 中文字幕 欧美 日韩 | 亚洲国产91 | 99九色 | 一区二区三区视频在线观看 | 国产高清一区二区三区 | 亚洲国产精品久久久 | 亚洲一区免费 | 黄视频欧美 | 国产精品美女久久久久久久久久久 | 免费一区二区三区 | 亚洲av毛片成人精品 | 一级欧美| 中文字幕 欧美 日韩 | 免费在线一区二区 | 久久久精品一区二区 | 一区二区三区四区不卡视频 | 老司机久久 | 精品国产乱码一区二区三区 | 免费在线观看成人 | 久久精品亚洲国产 | 日韩视频一区二区 | 成人在线视频免费观看 | 91精品国产乱码久久久久久久久 | 台湾佬伊人 | 黄色网址在线播放 | 成人欧美一区二区三区在线播放 | 自拍偷拍精品 | 亚洲第1页 | 岛国av免费看| japanhd成人 | 99久久婷婷国产精品综合 | 日韩中文字幕在线视频观看 | 欧美电影在线观看网站 | 久久一本 | 久久久观看 | 九九热精品视频 |