js 閉包原理

来源:https://www.cnblogs.com/linyabin/archive/2020/03/12/12375510.html
-Advertisement-
Play Games

閉包的定義:閉包是指有權訪問另一個函數作用域中的變數的函數 --《JavaScript 高級程式設計》。 如何理解這句話:其實就是指在函數a外面能夠訪問函數a裡面的函數b。 例如: 1 function a () { 2 var v = 123; 3 function b() { 4 console ...


閉包的定義:閉包是指有權訪問另一個函數作用域中的變數的函數  --《JavaScript 高級程式設計》。

如何理解這句話:其實就是指在函數a外面能夠訪問函數a裡面的函數b

例如:

 1 function a () {
 2   var v = 123;
 3   function b() {
 4     console.log(v);
 5   }
 6   return b;
 7 }
 8 
 9 var b = a();
10 b();  // 123

執行函數a時把函數b返回,此時函數b就保存到了a的外面,這時候就可以在a函數的外部對b進行訪問。

 

相關知識點:js作用域鏈

執行原理:

1、首先在預編譯全局代碼時,生成GO

  GO {

    a: function a() {...},

    b: undefined

  }

2、執行 var b = a();  此時對a函數進行預編譯並創建a 函數的AO 

  AO {

    v: undefined,

    a: undefined,

    b: function b() {...}

  }

3、創建a函數的作用域鏈

  a.[[Scopes]] = [AO, GO];  

4、由於函數的提升,會在a函數進行預編譯的時候創建b函數的AO

  b  AO {}

  b.[[Scopes]] = [AO(b), AO(a), GO]

5、執行 var v = 123;  在js預編譯中提到由於var v 的聲明已經得到了提升,所以此時只執行v = 123;對AO里的v 進行賦值。

  AO {

    v: 123,

    a: undefined,

    b: function b() {...}

  }

6、之後將函數b返回,此時a函數執行完畢,a函數對應的AO理應銷毀,但是由於在b函數中又對a函數的AO中的變數進行應用,所以a函數的AO不能被垃圾回收機制銷毀,但是會跟a函數斷開聯繫,當a函數再次執行,會重新創建一個a函數的AO。

7、在全局變數中使用b 接收函數a的返回,此時GO變為

  GO {

    a: function a() {...},

    b: function b() {...}

  }

 

8、全局裡的b

  在b函數中列印v變數,由於b函數的AO中沒有v變數,所以順著作用域鏈往上找,在a的AO中找到v並列印。

 

閉包優缺點:

  優點:

    1、屬性的私有化,在b返回後,處理b函數中能對v進行操作,其它地方都不能對v進行操作。

    2、防止變數污染。

  缺點:

    容易造成記憶體泄漏,因為如果後期不對全局中的b進行處理(例如:賦值為null),a函數的AO 會一直存在於記憶體中,如果多次調用a函數,容易導致記憶體中的垃圾數據越來越多造成記憶體泄漏。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • shell 腳本操作informix資料庫的簡單模板: functionName(){ dbaccess << ! database 庫名; sql語句; ! } 慄子1:更新數據 functionName(){ nameStr=$1 idStr=$2 dbaccess << ! database ...
  • 這樣如果備份的時候如果出現錯誤,那就看不出是哪裡出的問題,所以需要解決。 經過在網上查詢相關資料發現是客戶端字元集設置的和資料庫的字元集設置的不一致 資料庫的字元集查看語句為 select * from nls_database_parameters; 結果為utf-8字元集 那麼就需要將客戶端的字 ...
  • 開心一刻 樓主:心都讓你嚇出來了! 獅王:淡定,打個小噴嚏而已 前情回顧 神奇的 SQL 之 聯表細節 → MySQL JOIN 的執行過程(一)中,我們講到了 3 種聯表演算法:SNL、BNL 和 INL,瞭解了數據的查詢方式是 one by one,聯表方式也是 one by one ;並談到了 ...
  • MySql 是一種免費的關係型資料庫,相較於 MsSqlServer 和 Oracle 比較輕量化,安裝也很簡單,而且免費不需要的版權費用,個人認為一般的小項目採用還是比較合適的,當然也有部分數據量很大的項目會採用 MySql,不過個人認為 MySql 的多錶鏈接查詢能力不行,一但去組成 3個表以上 ...
  • 註意:無特殊說明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 ClipRect ClipRect組件使用矩形裁剪子組件,通常情況下,ClipRect作用於 、 、 、 、 、 、 組件,例如ClipRect作用於Alig ...
  • 教程/Articles 1. "說說 Flutter 中最熟悉的陌生人 —— Key" 插件/Librarys 1. "dna" 一個 flutter plugin. 輕量級的Dart到Native的超級通道,可直接在dart代碼中調用原生代碼,目前支持安卓 JAVA 和 iOS ObjC. 1. ...
  • 按照國際慣例,先放效果圖 1、js動態初始化Dom結構 首先在index.html中添加基本樣式 body{background:pink;text-align: center;} 加個移動端meta頭 <meta name="viewport" content="width=device-widt ...
  • 瀏覽器首碼: css3屬性:預覽版,還沒有最終版,所以有很多相容性問題,瀏覽器不識別。 瀏覽器為了使這些屬性相容,每個瀏覽器廠商都提供了一個屬於自己瀏覽器的語法規則,瀏覽器相容首碼。 主流瀏覽器:谷歌,IE,歐朋,火狐,蘋果 瀏覽器首碼: -wekit- 谷歌 -moz- 火狐 -ms- IE -o ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...