闭包不难懂:一次搞懂底层逻辑与应用技巧

前言

曾有一段时间,我也和许多人一样,每当时间推移,或是面试在即,便会上网搜索几篇关于闭包的面试题来背诵,试图以此来应对即将到来的挑战。

然而,随着时间的流逝,我渐渐意识到这种方法其实只是在浪费我的宝贵时间,而没有真正让我掌握闭包的精髓。于是,我决心深入探索闭包的奥秘,打破砂锅问到底,直到我能彻底搞懂它为止。

经过大量的资料搜索和深入研究,我终于可以说我已经彻底搞明白了闭包。现在,我想通过这篇文章,将我所学到的心得体会分享给大家,希望能帮助更多的人走出闭包的困惑,真正掌握这个重要的编程概念。

怎么学闭包?

在开始之前,允许小编再啰嗦一章。

小编以前学习也是每次都去网络搜索不一样的博主前辈们总结的闭包知识,但是由于每个博主擅长的技能都不一样,很难分辨哪篇文章讲的好,所以导致小编对于知识的理解参次不齐,全是碎片化的。

所以小编想在这边文章中,带大家用不同的视角去理解闭包,把这个闭包彻底消化成自己的知识,可以自己总结出一套概念,而不是再去搜索背诵别人总结后的概念。

引用《道德经》中的一句话:“无名万物之始,有名万物之母。”它告诉我们,无形的东西是一切有形之物的母亲,是宇宙的根本。借用这个理念,我们可以将其映射到编程的世界——闭包,它是JavaScript中的一个无形概念,却孕育了无数的功能和可能性。

废话完毕!GO!

什么是闭包?

想象一下

你在一家餐厅吃饭,服务员给你送来了一本菜单。尽管你离开了餐厅,那本菜单仍然记录着餐厅里的所有食物选项,让你能够回忆起那些美味的选择。

同样地,闭包就像那本菜单,它记住了函数被创建时周围的作用域,即使那个作用域已经不存在了。

  • 其实:闭包就是一个函数。
  • 而且:闭包是一个“记忆功能”很强的函数。
  • 有多强:它不仅能够记住自己的代码,还能够记住在哪里被创建,以及当时创建时周围环境的情况,包括那个时候的变量等。
  • 还不止:即使这个函数后来跑到别的地方去执行,它依然能够像在原来的地方一样“访问”那些变量。

闭包的优缺点

总结:

任何东西都有优缺点,闭包也不例外。

闭包在JavaScript中是一把双刃剑,它既提供了强大的功能,也带来了一定的挑战。

正确使用闭包可以让我们的代码更加优雅和高效,但如果不注意,可能会让我们的代码变得难以维护。

因此,我们需要像魔术师一样,既要善于利用工具,也要时刻警惕其潜在的风险。

列举:

闭包的优点:

  • 数据隐藏:闭包可以帮助我们隐藏数据(这就像是魔术师的助手在幕后协助完成表演,观众虽然看不见,但知道她的存在对整个表演至关重要)
  • 持久化变量:闭包允许我们在函数外部访问和操作函数内部的变量,即使这个函数已经执行完毕(这就像是魔术师将一些道具暂时“隐藏”起来,等需要的时候再拿出,给观众带来惊喜)
  • 减少全局变量污染:由于闭包可以封装变量,所以可以有效地减少全局变量的使用,避免了全局命名空间的污染(这就像是魔术师在自己的舞台上表演,不会影响到其他魔术师的表演空间)

闭包的缺点:

  • 性能问题:因为闭包会保存函数内部的作用域链,所以可能会导致内存占用较多,尤其是在使用大量闭包的情况下,可能会对性能产生负面影响(这就像是魔术师使用了太多的道具,虽然增加了表演的神秘感,但也可能让一些观众感到混乱)
  • 代码可读性下降:闭包的使用有时会使得代码结构变得复杂,特别是对于初学者来说,可能不容易理解闭包的工作原理(这就像是魔术师的表演过于复杂,普通观众可能无法完全领会其中的奥秘)
  • 潜在的内存泄漏:如果不当使用闭包,可能会导致一些变量无法被垃圾回收机制回收,从而造成内存泄漏(这就像是魔术师在表演结束后忘记清理道具,长此以往可能会影响到下一次表演)

闭包的使用场景

闭包的使用场景主要包括但不限于:

  • 延迟计算
  • 私有变量
  • 柯里化

延迟计算

设想你在图书馆借了一本书,但你决定等到回家后再阅读。你把书带回家,这就是一种延迟——你将阅读的行为推迟到了更合适的时候。

在JavaScript中,闭包可以用来创建一个函数,这个函数会在未来的某个时刻执行,而不是在定义它的时候就执行。这就像是你决定把书留到家再读一样。

function createReaderAction(bookTitle) {
  return function() {
    console.log(`Reading "${bookTitle}" now.`);
  };
}

const readBook = createReaderAction("JavaScript Cookbook");
// 相当于你把书带回家,准备稍后阅读
readBook(); // 输出: Reading "JavaScript Cookbook" now.

在这个例子中,createReaderAction是一个工厂函数,它返回了一个闭包readBook,这个闭包保存了传入的书籍标题。只有当你调用readBook()的时候,它才会打印出消息,就像是你回到家开始阅读一样。

延迟计算的具体应用场景包括但不限于:防抖和节流(可以参考我以前的笔记)

私有变量

在你的日记里,你记录了许多私人想法,这是私有的,别人无法直接查看。

在JavaScript中,闭包可以用来创建私有变量,这些变量只能通过特定的方法来访问,就像你的日记只对你开放一样。

function createAccount(balance) {
  return {
    deposit: function(amount) {
      balance += amount;
    },
    withdraw: function(amount) {
      if (balance >= amount) {
        balance -= amount;
        return true;
      } else {
        return false;
      }
  };
}

const myAccount = createAccount(100);
myAccount.deposit(50); // 存钱
console.log(myAccount.balance); // 报错,因为balance不是公开的

在这里,balance是私有的,只能通过depositwithdraw方法来访问和修改。这保证了账户的安全性,正如你的日记内容不会轻易被人窥探。

柯里化

假设你有一个食谱,你想制作多种口味的蛋糕,但是基础配方是一样的。你会一次又一次地使用同一个配方,只是改变其中的一些配料。

在JavaScript中,柯里化是一种技术,它允许你将一个函数转化为接受几个参数的函数,然后返回一个新的函数,这个新函数等待接收剩余的参数。

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function(...newArgs) {
        return curried.apply(this, args.concat(newArgs));
      };
    }
  };
}

function add(a, b) {
  return a + b;
}

const addFive = curry(add, 5);
const addTen = curry(add, 10);

console.log(addFive(3)); // 使用curry预设第一个参数为5,输出8
console.log(addTen(3)); // 使用curry预设第一个参数为10,输出13

在这个例子中,curry函数返回一个新的函数,这个新函数记住前面传递的参数,直到它接收到足够的参数来执行原始的add函数。

结语

通过理解闭包的工作原理,你可以创造出更加模块化和功能强大的代码,就像是在你的写作中加入了一种新的笔触,使得你的作品层次丰富,意味深长。不要仅仅依赖记忆中的概念,而是要去实践,去体验闭包的力量,并且形成你自己对它的理解。这样,无论何时何地,你都能够运用自如,写出既优雅又高效的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/598237.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么将pdf的文件内容保存到mysql数据库中?

要将PDF导入到MYSQL,首先一步就是要先将PDF内容结构化,如果其内容为非结构化,则导入MYSQL的意义不大,具体操作方法如下: 将PDF文件的内容保存到MySQL数据库中通常涉及几个步骤。PDF文件包含的是格式化文本、图像和其他…

​XMall商城微信小程序前端技术解析

摘要 随着移动互联网的深入发展,微信小程序以其轻量级、便捷性和即用即走的特点,成为了众多企业和开发者关注的焦点。XMall商城微信小程序前端作为一款开源项目,以其精美的页面设计、丰富的功能和高效的性能,受到了广大开发者和用…

深度学习之基于Matlab BP神经网络烟叶成熟度分类

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 烟叶的成熟度是评估烟叶品质的重要指标之一,它直接影响着烟叶的口感、香气和理化特性。传…

还不懂 RESTful 接口是什么?快进来看看

RESTful是指基于REST(Representational State Transfer,表现层状态转移)架构风格的Web服务。REST是一种设计原则和架构风格,而不是标准,它用于指导如何构建易于交互、高效、可扩展的网络系统。RESTful服务通常使用HTTP…

Oracle Database 23ai Free RPM Installation On Oracle Linux 8 (OL8)

Oracle刚刚发布了最新的Oracle database 23ai版本测试安装包,有兴趣的小伙伴可以安装体验一下。 关于安装的介质可以去如下地址下载: Oracle linux 8.9 Oracle Linux ISOs | Oracle, Software. Hardware. Complete. Oracle database 23ai安装包 Get Star…

Read timed out. (python 安装第三方库超时)

不少人在安装python第三方库的时候经常发生下面情况 解决方法就是往上找 我这里就是 jupyterlab-4.1.8-py3-none-any.whl安装时间过长,失败 那就去国内镜像网站下载下来离线安装 https://pypi.tuna.tsinghua.edu.cn/simple/xxx(xxx就是你的包名&#…

AI绘画Stable Diffusion【艺术写真】:冰雪奇缘,使用ReActor插件实现AI写真

大家好,我是设计师阿威。 前面分享过几篇使用AI绘画Stable DIffusion中的InstantID插件实现AI写真的制作方法。 目前换脸插件有很多,比较典型的有Roop,ReActor,IP-Adapter,InstantID,就目前效果来看,InstantID单张图像换脸的相似…

数据结构:时间复杂度/空间复杂度

目录 一、时间复杂度 定义 常见的时间复杂度 如何计算时间复杂度 计算方法 三、实例分析 二、空间复杂度 定义 重要性 常见的空间复杂度 二、空间复杂度 定义 重要性 常见的空间复杂度 计算方法 三、实例分析 大O的渐进表示法 最好情况(Best Case…

【前端】实现表格简单操作

简言 表格合并基础篇 本篇是在上一章的基础上实现,实现了的功能有添加行、删除行、逆向选区、取消合并功能。 功能实现 添加行 添加行分为在上面添加和在下面追加行。 利用 insertAdjacentElement 方法实现,该方法可以实现从前插入元素和从后插入元…

一起长锈:3 类型安全的Rust宏(从Java与C++转Rust之旅)

讲动人的故事,写懂人的代码 故事梗概:在她所维护的老旧Java系统即将被淘汰的危机边缘,这位在编程中总想快速完事的女程序员,希望能转岗到公司内部使用Rust语言的新项目组,因此开始自学Rust;然而,在掌握了Rust编程知识之后,为了通过Rust项目组的技术面试,使得转岗成功而…

【C语言】动态分配内存

内存的五大分区 1、堆区(heap)——由程序员分配和释放, 若程序员不释放,程序结束时一般由操作系统回收。注意它与数据结构中的堆是两回事 2、栈区(stack)——由编译器自动分配释放 ,存放函数的…

力扣刷题:四数相加Ⅱ

题目详情: 解法一:暴力枚举 对于这道题,我们的第一思路就是暴力枚举,我们可以写一个四层的for循环进行暴力匹配,只要相加的结果等于0就进行统计。但是我们会发现,我们的事件复杂度为O(N^4)事件复杂度非常大…

vue使用pdfjs-dist在电脑上展示PDF文件

安装 安装的时候一定要带上版本号,这里采用的是2.0.943(因为这个版本对于我目前的项目比较合适可以正常使用,其他版本大概率会报错),当前项目使用的是vue2,vue的版本是2.5.10 npm install pdfjs-dist@2.0.943 查看版本发现这玩意版本非常之多 使用 在使用pdfjs-dist库…

张大哥笔记:自媒体人10种赚钱方法

很多人都在做自媒体,比如平台广告分成、广告收入、公关宣传、品牌植入、演讲、会员制、出书、线下活动。那么本文介绍了自媒体人10种赚钱方法,供大家参考: 1、打造个人IP 什么是个人IP?在百度百科上是这样解释的:指个…

深度学习之基于YOLOv5目标检测可视化系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着深度学习技术的快速发展,目标检测在多个领域中的应用日益广泛,包括…

字节人都用的婚恋交友相亲平台有哪些?聊聊互联网大厂的人是怎么脱单的!

虽然在字节这样的公司上班,也算是人中之人了。但是也耐不住29岁了,快成大龄剩女了。迫于长辈的催婚压力,所以带着任务体验了一遍各大相亲交友平台,以下是我的使用感受。 1、青藤之恋:偏相亲定位,曾经高学历…

libcity 笔记:libcity/executor/traj_loc_pred_executor.py

1 构造函数 2 _build_optimizer 根据配置中指定的优化器类型创建并返回一个适合用于模型训练的优化器对象 3 _build_scheduler 构建一个学习率调度器(scheduler) 4 train 5 run 6 _valid_epoch 7 load_model & save_model 保存/加载模型的状态字…

一起长锈:4 默认不可变的变量绑定与引用(从Java与C++转Rust之旅)

讲动人的故事,写懂人的代码 故事梗概:在她所维护的老旧Java系统即将被淘汰的危机边缘,这位在编程中总想快速完事的女程序员,希望能转岗到公司内部使用Rust语言的新项目组,因此开始自学Rust;然而,在掌握了Rust编程知识之后,为了通过Rust项目组的技术面试,使得转岗成功而…

Oceanbase all-in-one单机版部署,通过MySQL客户端连接OB租户,DBEAVER 客户端连接MySQL租户。

一.Oceanbase all-in-one单机版部署 1.修改资源限制。 vim /etc/security/limits.conf root soft nofile 655350 root hard nofile 655350 * soft nofile 655350 * hard nofile 655350 * soft stack unlimited * hard stack unlimited * soft nproc 655360 * hard nproc 6553…

【ElasticSearch】IK分词器中停用词问题

问题描述 在ES中进行部分关键词搜索时,搜索无结果,如搜索 【IT】 环境描述 中文分词插件 这里使用的是 analysis-ik 分词调试 POST test_index/_analyze {"text":"IT Manager","analyzer": "ik_max_word"…
最新文章