专栏首页HTML5学堂轻松但深入的学习闭包原理 —— 曾让几乎所有JS新手痛恨的知识

轻松但深入的学习闭包原理 —— 曾让几乎所有JS新手痛恨的知识

HTML5学堂-码匠:这或许是你看过的,最浅显易懂的一篇关于闭包原理的讲解!

闭包的官方定义

官方定义:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

不得不说,对于新手来说,闭包的官方定义,不如不看,看完之后反而让人 心碎 + 懵逼

不可缺少的前置知识

想要看懂闭包,如下的这四种知识,你必须掌握,一个都不能少!缺任何一个,都会让你无法理解闭包!!!

作用域

你必须知道的是!作用域分为局部作用域和全局作用域,而函数,会创建局部作用域

在使用变量时,会优先在其作用域下进行空间的寻找,如果没有找到,则寻找其上一级作用域

如果还没有,则继续向上一级查找,遵循该规则不断反复,直到寻找到window为止

如上效果中,h5course函数中的user会优先查找自身作用域,发现存在user变量。因此,打印出的结果为 '码匠' 。

如上效果中,h5course函数中的user会优先查找自身作用域,发现并不存在user变量,此时向其上一级(父级)作用域查找,其上一级作用域为window(全局),找到user的存储空间。因此,打印出的结果为 'HTML5学堂' 。

函数的返回值

你能否正确解读这段代码的含义呢。

Tips:con是一个标签,获取con标签的过程,在代码中已省略

这段代码的含义,是?

A:在点击con元素时,运行user函数

B:在点击con元素时,执行user函数的运行结果(在此,请不要考虑user函数的运行结果是什么)


如果你选择的是B,恭喜你,B是正确答案!

在这个位置,需要注意,当将一个函数的执行【如上的user()】而非函数名赋值给某一个属性/方法时,指的是:将这个函数的运行结果赋值给该属性/方法。

此外,你还需要了解的一个知识是:函数的返回值(return后面的内容)为函数的运行结果,在没有return时,返回的是undefined。

内存释放 / 垃圾回收机制

JS为了保证程序的运行速度,会及时进行垃圾回收,让内存空间得到合理的释放。

说的浅显一点:

大段大段的JS代码,在执行时势必会消耗内存,而为了节省内存空间,JS当中的代码一旦“不被”使用,就会被“回收”,相应的空间也会被释放,从而保证代码、程序的运行效率。

对于JS中的全局变量,当浏览器卸载(关闭)相应页面时,会被删除(全局变量的生命周期结束)

而对于局部变量,在函数(相应局部作用域)执行过程中,会创建一个空间进行存储,而当函数结束时,这个空间就会被释放,变量被回收。

但是!!!

当相应函数内部的变量,被该函数(外部函数)的内部函数所使用时,该函数(外部函数)的变量不能够被释放!

形参与实参

在函数当中,必须要分清楚何为实参,何为形参

此外,你还必须知道:形参在函数中,会默认创建一个存储空间!

重复!形参在函数中,会默认创建一个存储空间

尝试分辨一下如下代码中的str吧!

arg中的str和调用时的str并不是同一个。

函数调用时用到的str是全局变量,而传入arg函数中的str相当于是在局部作用域当中,创建了一个str。

如果你足够清晰形参与实参知识的话,你会发现,如下代码和上面的代码,功能是等价的!(只是换了个名字)

闭包的使用场景

实际开发中的闭包

在实际的开发当中,闭包通常伴随这样的特点出现:

  • 为多标签添加类似操作、需要使用到“索引”, “索引”使用的时机,并非是代码运行时立即使用,而是在某种情况下触发(比如用户点击)(Tips:会使用到for,但不是只用for就能够解决的)

还有一类场景,也会出现闭包:

  • 希望能够多次调用一个功能函数,每次调用函数时是基于前一次调用情况的。

光靠说,想象出使用的场景可能还稍有些困难,我们看个实例。

案例 - 点击标签弹出索引值

Tips:出于篇幅考虑,如下案例代码当中,结构、样式代码均已省略。

涉及到索引值,触发条件为:

JS代码都执行完毕之后,页面加载完成,用户在用鼠标点击时才执行相关操作。

终于可以开心的聊闭包了

闭包!!!

使用闭包,能够将JS运行中,原本会被执行覆盖的变量值存储下来,以便于后期使用。

原理:借助函数的立即执行参数以及函数的return返回值多创建了一层作用域。从而实现外部函数持续性被引用而不能释放内存空间,将值存储下来

我这里说的这段原理虽然比官方定义简单一些了,但是可能还是比较难咀嚼,一起来在实例当中理解这个原理吧!

借助实例,理解原理与实现过程

最终效果与代码

功能需求为:用户在点击某标签时,能够实现输出最初num值(案例中为1)

Tips:在这个案例当中,只有在点击时才能够输出,而用户点击时JS代码已经运行完成了,全局中的num变量会变为100。

实现过程

Step1 构建两层结构,外部函数与内部函数

Step2 立即调用外部函数,并将num值以参数的形式传入到外部函数当中,外部函数接收到了实参(num),并存储在了自己的n这个变量当中

Step3 实现变量的存储功能 —— 由于函数内部属于局部作用域,在不使用时就会被释放,为了不让其释放,就再在其内部创建一个函数。

内部函数中的n实际上使用的是外部函数的n。

由于外部函数中的变量(n)一直被内部函数引用,所以外部函数中的变量不能被释放

Step4 实现用户操作时,执行相应内部函数功能 —— 内部函数作为返回值而存在

闭包的经典面试真题

闭包,也是各个公司面试时的高频考点。

闭包的面试真题以及解析,点击小程序查看吧!

开开心心每一天

生活艰辛,代码不易,但,不要忘记微笑!

版权声明:该图来自“【美】莉兹·克里莫 (author)”的书籍《你今天真好看》

本文分享自微信公众号 - HTML5学堂(h5course-com),作者:HTML5学堂(码匠)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-10-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 函数声明与表达式的区别

    HTML5学堂:函数有不同的定义方法,一种是函数声明,另一种是函数表达式,那么这两种有何区别呢? 函数声明的基本语法 function functionName...

    HTML5学堂
  • JS 计时器参数剖析与真题

    HTML5学堂-码匠:计时器的第一个参数,包含几种不同的书写方法,可以是函数名,匿名函数,JS代码字符串,还有一些面试题当中会出现“函数调用”的书写方式。 那么...

    HTML5学堂
  • 2015.12.17 HTML5真题练习

    HTML5学堂:每天一道题,强壮程序员!今日主要涉及12.16日关于函数返回值的题目解答,以及一道涉及闭包的题目。 HTML5真题【2015.12.16】答案解...

    HTML5学堂
  • Python数据类型之字符串第四季

    各位小伙伴们 “黑一”快乐 本节课非常非常重要 请各位小伙伴 一定认真理解和学习 技术要点: 内建函数 函数的理解 如何使用一个函数 capitalize()函...

    企鹅号小编
  • 谈谈自己的理解:python中闭包,闭包

    闭包这个概念好难理解,身边朋友们好多都稀里糊涂的,稀里糊涂的林老冷希望写下这篇文章能够对稀里糊涂的伙伴们有一些帮助~

    py3study
  • Python第十三课:函数II

    在上一课中我们主要学习了函数的输入,我们现在结合前面学到的关于文件的操作来写一些函数达到处理文件的功能。

    HuangWeiAI
  • Python第十二课:函数I

    对于一门编程语言而言函数是一个极其重要的元素,一般而言函数可以帮助我们分离各个模块实现分层,让程序员更方便编程的同时也增强了程序的可读性。想象一下如果有一个一千...

    HuangWeiAI
  • 房价会崩盘吗?教你用 Keras 预测房价!(附代码)

    书中其中一个应用例子就是用于预测波士顿的房价,这是一个有趣的问题,因为房屋的价值变化非常大。这是一个机器学习的问题,可能最适用于经典方法,如 XGBoost,因...

    AI研习社
  • C语言之函数

      结构化程序设计主张按功能来分析需求,主要原则自顶向下,逐步求精,模块化等。 主张按功能把软件系统逐步细分,每个功能都负责对数据进行一次处理,每个功能接收一些...

    互联网金融打杂
  • 【Python环境】Python函数式编程指南(1):概述

    1. 函数式编程概述 1.1. 什么是函数式编程? 函数式编程使用一系列的函数解决问题。函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。任何情况下...

    陆勤_数据人网

扫码关注云+社区

领取腾讯云代金券