深入理解JS闭包

深入理解JS闭包闭包的理解

大家好,又见面了,我是你们的朋友全栈君。

关于JS中闭包的理解,相信很多人都和笔者一样刚开始很是困惑。笔者也是在看了很多前辈的文章后,总结出一点自己的理解。记录与此,囿于笔者水平有限 ,若有错误之处,恳请不啬赐教。

你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数,因为ES6有了块级作用域的概念)。

函数 – JavaScript | MDN(上面这句话摘自这个网址)

第一部分:初遇闭包

JavaScript 闭包 | 菜鸟教程

深入理解JS闭包

什么是闭包?闭包有什么作用?这是我遇到闭包时的第一反应。

闭包在JavaScript高级程序设计(第3版)中是这样描述:闭包是指有权访问另一个函数作用域中的变量的函数。

那么闭包的作用也就很明显了。

1. 可以在函数的外部访问到函数内部的局部变量。 
2. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。

在上面的代码中,闭包指的就是function () {return counter += 1;}这个函数。首先解释一下这段代码,在变量add被赋值之前,第一个function执行了一次(执行且仅会执行一次),因为这是一个函数表达式声明方式并且声明后加上了(),所以会自动执行一次。执行后add被赋值(匿名函数)了,add= function () {return counter += 1;} 。然后每次调用add()函数时,返回的都是内层匿名函数的执行结果,因为内层匿名函数在外层函数的内部,所以即使外层函数执行完了,第二个函数依然能访问counter(JS设计的作用域链,当前作用域能访问上级的作用域)。

闭包是可以在某个函数的外部访问到该函数作用域中变量的其它函数。而被访问的变量可以和函数一同存在。即使另一个函数已经运行结束,导致创建变量的环境销毁,也依然会存在,直到访问变量的那个函数被销毁。解释一下:变量add 引用了匿名函数,而匿名函数引用了 counter 变量。所以 add 没有置为null之前,counter 就是有用的,不会被GC(垃圾回收).

当然,如果仅仅是做一个简单的计数器,大可不用这样麻烦。下面这简短的代码就能轻松实现。

var a = 0;
function myFunction(){
	a++;
    document.getElementById("demo").innerHTML = a;
}

推荐一篇博客:对JavaScript中闭包的理解_王宜明的博客-CSDN博客(写得很有深度)

第二部分:牛客翻船

依次点击4个li标签,哪一个选项是正确的运行结果?_搜狗笔试题_牛客网

深入理解JS闭包

下面是这个题目的解答:
每个li标签的onclick事件执行时,本身onclick绑定的function的作用域中没有变量i,i为undefined,则解析引擎会寻找父级作用域,发现父级作用域中有i,且for循环绑定事件结束后,i已经赋值为4,所以每个li标签的onclick事件执行时,alert的都是父作用域中的i,也就是4。这是作用域的问题。

闭包只能取得包含函数中任何变量的最后一个值。因为别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。

这是在循环体中创建闭包的常见错误。闭包 – JavaScript | MDN(一定要看这篇)

这里面给onclick赋值的是闭包。很多人会问为什么是闭包?之前闭包不是函数A里的函数B吗?函数B用来访问函数A的变量,称函数B是闭包,题目中只有一个函数为什么也是闭包。其实,用两个函数形成闭包只是一般形式。闭包真正的含义是,如果一个函数访问了此函数的父级及父级以上的作用域变量,就可以称这个函数是一个闭包。全文的核心

<script>
    var a = 1;
    (function test (){
		alert(a);
	})()
</script>

所以上面的function都可以称之为闭包(匿名闭包函数)。

这里还是作用域的问题,那么我们把每次的i都保存到一个变量中,匿名闭包就可以实现想要的效果。

var elements=document.getElementsByTagName('li');
    var length=elements.length;
    for(var i=0;i<length;i++){
        elements[i].onclick=function(num){
        return function() {
                alert(num);
        };
    }(i);
    }

这样就使用了闭包,这里面的闭包指的是function() {alert(num);};第二个function里面弹出的num是第一个function的参数,通过(i)执行了这里面的第一个函数,同时i的值被保存到num中。每个点击事件中都有一个局部变量num,num保存的是相应的i值。

第三部分:let的横空出世

上面的牛客题目只需要将for(var i=0;i<length;i++)中的var改成let就能实现想要的效果,这让在循环体内创建闭包具有更好的可读性。

深入理解JS闭包

let的到来,让令人诟病的JS获得了一丝生机,也补上了JS没有块级作用域的短板。ECMAScript6还有很多新特性,笔者也在不断学习中。

第四部分:闭包的应用

函数工厂和闭包模拟私有方法

闭包 – JavaScript | MDN(这篇讲得很好,希望读者们读透)

闭包理解的视频推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150088.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 回归分析详解及matlab实现[通俗易懂]

    回归分析详解及matlab实现[通俗易懂] 回归分析方法 想要资源的请关注公众号:在一起的足球自动获取资源和数十种经典算法,帮助各位提升自己之前留的是自己的qq号感觉好多资源都不能让大家自行选择本着开源的精神,在公众号挂了百度云链接,这样晚上就不用被吵醒了当人们对研究对象的内在特性和各因素间的关系有比较充分的认识时,一般用机理分析方法建立数学模型。如果由于客观事物内部规律的复杂性及人们认识程度的限制,无法分析实际对象内在的因果关系,…

    2022年10月26日
  • 微信模拟地理位置_伪装微信地理位置

    微信模拟地理位置_伪装微信地理位置1.允许应用程序打开系统窗口,显示其他应用程序2.允许应用程序访问GMail账户列表3.允许应用程序请求从AccountManager验证4.允许应用程序管理AccountManager中的账户列表5.允许应用程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息6.允许应用程序获取网络信息状态7.允许应用程序访问网络连接8.允许应用程序获取模拟定位信息用于开发者调试应用9.允许应…

  • 如何卸载cuda

    如何卸载cuda============Summary============Driver:InstalledToolkit:Installedin/usr/local/cuda-10.2/Samples:Installedin/home/game/,butmissingrecommendedlibrariesPleasemakesurethat-…

  • sstream读取文件

    sstream读取文件对于如下图所示的数据文件:274表示有274个点对,以下每一行代表一个点对,每一行的四个数从左到右依次是一个第一个点的x坐标、y坐标、第二个点的x坐标、y坐标,现在要把点对数和每个点对读取并存储,具体代码如下:#include<iostream>#include<sstream>#include<fstream>#include<string&…

  • 无线基础知识

    无线基础知识一、WIFI发展历程:二、调制:所谓调制,就是将电信号转换为无线电波的过程,反之则称为解调,其核心技术是调制方式,调制方式越高阶,转换过程中数据密度就越高。调制方式决定每个子载波能传输多少数据,

  • java 异或加密_使用异或实现一个简单的加密或解密

    java 异或加密_使用异或实现一个简单的加密或解密/**Copyright(C)2017,MegatronKing**LicensedundertheApacheLicense,Version2.0(the”License”);youmaynotusethisfileexcept*incompliancewiththeLicense.YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/.

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号