一篇文章理解js閉包和作用于原理

一、js閉包的作用原理

JS閉包是指內部函數訪問外部函數變量的機制,常用于數據封裝和模塊化。典型應用包括創建私有變量、解決循環中的異步問題、實現函數柯里化等。案例分析展示了閉包在計數器、防抖函數等場景的使用,同時揭示了可能的內存泄漏風險。正確使用閉包需理解作用域鏈,合理管理內存,避免變量意外共享。閉包在異步編程和函數式編程中發揮重要作用,是JavaScript的核心特性之一。


二、案例分析

1. 基本閉包示例

function outerFunction(x) {// 外部函數的變量let outerVariable = x;// 內部函數(閉包)function innerFunction(y) {console.log(`外部變量: ${outerVariable}, 內部參數: ${y}`);return outerVariable + y;}return innerFunction;
}const closure = outerFunction(10);
console.log(closure(5)); // 輸出: 外部變量: 10, 內部參數: 5, 返回: 15

2.閉包的實際應用 - 數據私有化

function createCounter() {let count = 0; // 私有變量return {increment: function() {count++;return count;},decrement: function() {count--;return count;},getCount: function() {return count;}};
}const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
// console.log(counter.count); // undefined - 無法直接訪問私有變量

3. 閉包在循環中的經典問題

// 錯誤示例 - 所有函數都會輸出3
console.log('錯誤示例:');
for (var i = 0; i < 3; i++) {setTimeout(function() {console.log(`錯誤示例 - i的值: ${i}`); // 都輸出3}, 100);
}// 正確示例1 - 使用閉包
console.log('正確示例1 - 使用閉包:');
for (var i = 0; i < 3; i++) {(function(index) {setTimeout(function() {console.log(`閉包解決 - index的值: ${index}`);}, 200);})(i);
}// 正確示例2 - 使用let
console.log('正確示例2 - 使用let:');
for (let i = 0; i < 3; i++) {setTimeout(function() {console.log(`let解決 - i的值: ${i}`);}, 300);
}

4. 模塊模式

const MyModule = (function() {let privateVariable = 0;function privateFunction() {console.log('這是私有函數');}return {publicMethod: function() {privateVariable++;privateFunction();console.log(`私有變量值: ${privateVariable}`);},getPrivateVariable: function() {return privateVariable;}};
})();MyModule.publicMethod(); // 這是私有函數, 私有變量值: 1
console.log(MyModule.getPrivateVariable()); // 1

5. 函數柯里化(Currying)

function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args);} else {return function(...nextArgs) {return curried.apply(this, args.concat(nextArgs));};}};
}function add(a, b, c) {return a + b + c;
}const curriedAdd = curry(add);
console.log('\n=== 柯里化示例 ===');
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6

6. 作用域鏈示例

let globalVar = 'global';function level1() {let level1Var = 'level1';function level2() {let level2Var = 'level2';function level3() {let level3Var = 'level3';console.log('\n=== 作用域鏈 ===');console.log(`訪問level3變量: ${level3Var}`);console.log(`訪問level2變量: ${level2Var}`);console.log(`訪問level1變量: ${level1Var}`);console.log(`訪問全局變量: ${globalVar}`);}level3();}level2();
}level1();

7. 閉包的內存管理

function createHeavyObject() {const heavyData = new Array(1000000).fill('data');return function() {// 只返回需要的數據,避免整個heavyData被保持在內存中return heavyData.length;};
}const getLength = createHeavyObject();
console.log('\n=== 內存管理 ===');
console.log(`數組長度: ${getLength()}`);

8. 實際應用:防抖函數

function debounce(func, delay) {let timeoutId;return function(...args) {clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(this, args);}, delay);};
}const debouncedLog = debounce((message) => {console.log(`防抖執行: ${message}`);
}, 1000);// 模擬快速調用
console.log('\n=== 防抖示例 ===');
debouncedLog('第一次調用');
debouncedLog('第二次調用');
debouncedLog('第三次調用'); // 只有這個會執行

?三、總結

  1. 閉包允許內部函數訪問外部函數的變量

  2. 閉包可以用于數據私有化和模塊模式

  3. 注意閉包可能導致的內存泄漏問題

  4. 閉包在異步編程和函數式編程中非常有用

  5. 理解作用域鏈對掌握閉包至關重要

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84626.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84626.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84626.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GUI絲滑教程-python tinker

在 Tkinter GUI 應用中&#xff0c;線程可以幫助你在后臺執行長時間運行的任務&#xff0c;而不阻塞界面響應。下面是一些技巧&#xff0c;幫助你在使用線程時避免 Tkinter 界面卡頓的問題。 為什么 Tkinter 界面會卡頓&#xff1f; Tkinter 使用 主線程 來處理 UI 更新&…

第一部分-數據通信網絡基礎

目錄 一、什么是網絡通信&#xff1f; 二、網絡通信設備的基本識別 1.雙絞線 2.集線器&#xff08;物理層設備&#xff09; 3.中繼器&#xff08;物理層設備&#xff09; 4.接入交換機 5.匯聚交換機 6.核心交換機 7.路由器 8.無線路由器 9.光貓 一、什么是網絡通信&#xff1f;…

windows電腦解決筆記本搜索不到wifi問題

windows筆記本電腦明明打開了wifi功能&#xff0c;卻搜索不到wifi&#xff0c;此問題可能是網絡適配器被禁用的原因導致&#xff0c;通過以下方法也許能解決&#xff0c;無需重啟電腦 1、右鍵點擊網絡或wifi圖標&#xff0c;打開界面”網絡和internet“ 2、選擇”高級網絡設置…

C# 界面檢測顯示器移除并在可用顯示器上顯示

C# 檢測顯示器被移除&#xff0c;將界面在當前可用的顯示器上顯示&#xff0c;避免程序在任務欄點擊無響應。 using System; using System.Linq; using System.Windows.Forms;public class MonitorWatcher : IDisposable {private readonly Form _targetForm;private Screen …

JAVA實戰開源項目:青年公寓服務平臺 (Vue+SpringBoot) 附源碼

本文項目編號 T 233 &#xff0c;文末自助獲取源碼 \color{red}{T233&#xff0c;文末自助獲取源碼} T233&#xff0c;文末自助獲取源碼 目錄 一、系統介紹二、數據庫設計三、配套教程3.1 啟動教程3.2 講解視頻3.3 二次開發教程 四、功能截圖五、文案資料5.1 選題背景5.2 國內…

阿里云服務狀態監控:實時掌握云服務健康狀況

前言 在云計算時代,企業和開發者越來越依賴云服務提供商的基礎設施和服務。當我們的應用部署在云上,服務的可用性和穩定性就與云服務提供商息息相關。一旦云服務出現故障或維護,可能會對我們的業務造成直接影響。因此,實時了解云服務的運行狀態變得尤為重要。阿里云作為國…

使用VSCode開發FastAPI指南

1概述 FastAPI 是一個現代的高性能 Web 框架&#xff0c;用于使用 Python 構建 API。它旨在讓開發者輕松快速高效地構建 API&#xff0c;同時提供 API 的自動驗證、序列化和文檔記錄等功能&#xff0c;使其成為構建 Web 服務和微服務的熱門選擇。 在這個 FastAPI 教程中&#…

2025年硬件實習/秋招面試準備

前言 暑期即將到來&#xff0c;有很多研一研二以及大三大四的同學準備硬件類&#xff08;硬件研發、嵌入式硬件、layout、電源設計、射頻、硬件測試、工藝、FAE&#xff09;的實習或秋招。鑒于此&#xff0c;總結一下網友們秋招、實習中的硬件高頻考點&#xff0c;并分析他們是…

VSCode - Trae 插件關閉彈出框代碼補全

Trae 插件關閉彈出框代碼補全 彈出框代碼補全與非彈出框代碼補全 如下是彈出框代碼補全 如下是非彈出框代碼補全 關閉 / 啟用彈出框代碼補全 點擊 【管理】&#xff08;小齒輪&#xff09; -> 點擊 【設置】 取消勾選&#xff08;如果需要啟用&#xff0c;則勾選即可&…

Elasticsearch從安裝到實戰、kibana安裝以及自定義IK分詞器/集成整合SpringBoot詳細的教程ES(三)

DSL官方地址&#xff1a; DSL查詢分類 Elasticsearch提供了基于JSON的DSL&#xff08;https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl&#xff09;來定義查詢。常見的查詢類型包括&#xff1a; 查詢所有&#xff1a;查詢出所有數據&#xff0…

我們來學mysql -- keepalive主從高可用

keepalive主從高可用 簡明扼要安裝KP場景“高可用”配置主keepalived.conf從keepalived.confmysql_check.sh 高可用驗證KP運行情況通過vip連接mysqlvip連接上創建數據庫關閉主庫所在服務器的KPvip連接上再次創建數據庫 結尾 簡明扼要 搭建mysql的主從八股文如是&#xff1a;主…

Compose筆記(二十六)--DatePicker

這一節主要了解一下Compose中的DatePicker,DatePicker是一個用于選擇日期的組件&#xff0c;它提供了直觀的界面讓用戶可以通過日歷視圖或直接輸入來選擇年、月、日。我們在開發中時常會用到日期選擇器&#xff0c;簡單總結如下: API: DatePickerDialog onDismissRequest&…

【靶場】upload-labs-文件上傳漏洞闖關

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言1.第一關1.保存html頁面2.修改頁面html3.訪問修改后的本地html文件4.上傳php文件5.訪問上傳的php2.第二關1.抓上傳包修改文件類型2.上傳成功3.第三關1.phtml php3會被解析為php原理2.上傳成功4…

基于 Transformer RoBERTa的情感分類任務實踐總結之四——PGM、EMA

整合了以下五大核心技術&#xff1a;R-Drop、PGM 對抗訓練、EMA、標簽平滑、CosineAnnealing 學習率調度。 1. R-Drop&#xff08;Regularized Dropout&#xff09; 原理&#xff1a;同一個樣本做兩次前向傳播&#xff08;同 dropout mask&#xff09;&#xff0c;計算兩次輸…

錄制mp4 rospy

ros 預覽攝像頭 #!/usr/bin/env python import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge import cv2# 初始化 bridge bridge CvBridge()def image_callback(msg):# 將ROS圖像消息轉換為OpenCV圖像cv_image bridge.imgmsg_to_cv2(msg, desir…

超簡單部署離線語音合成TTS和語音識別

一篇文章講清楚超簡單 離線語音合成TTS 和 離線語音識別 系統部署 本文只介紹兩個輕量級的 語音合成用piper, 語音識別用vosk 部署簡單,效果勉強 語音合成 推薦 piper (其他沒用過) 安裝 linux下安裝 pip install piper-tts下載模型(63M) 中文模型下載 zh_CN-huayan-medi…

【算力網】

一、算力網-DNS 1.1、核心架構設計 1.1.1 設計框架 基于SRv6的智能DNS算法設計框架&#xff0c;結合IPv6路由可編程性、動態路徑優化及業務感知能力&#xff0c;實現網絡性能與用戶體驗的雙重提升&#xff1a;? ?SRv6-DNS融合架構? ?控制平面?&#xff1a; DNS服務器集…

shell分析nginx日志的指令

shell指令 查看有多少個IP訪問&#xff1a; awk {print $1} log_file|sort|uniq|wc -l 查看某一個頁面被訪問的次數&#xff1a; grep "/index.php" log_file | wc -l 查看每一個IP訪問了多少個頁面&#xff1a; awk {S[$1]} END {for (a in S) print a,S[a]} …

CMS軟件以及常見分類

CMS&#xff08;Content Management System&#xff0c;內容管理系統&#xff09;是 讓非技術人員也能便捷創建、編輯、管理網站內容的軟件 &#xff0c;核心是 分離 “內容” 和 “頁面設計”&#xff08;內容存在數據庫&#xff0c;頁面用模板生成&#xff09;&#xff0c;無…

Spring @Value 典型用法

典型用法 注入常量值 Value("Hello World") private String message;注入配置文件中的屬性值&#xff08;如 application.properties&#xff09; // 假設你有如下配置&#xff1a; app.nameMyApp app.version1.0.0// Java 類中使用&#xff1a; Value("${ap…