JavaScript——以简单的方式理解闭包

      闭包,在一开始接触JavaScript的时候就听说过。首先明确一点,它理解起来确实不复杂,而且它也非常好用。那我们去理解闭包之前,要有什么基础呢?我个人认为最重要的便是作用域(lexical scope),如果对作用域和作用域链不理解的同学最好自己先去学一学,再回过头来,理解闭包,就更加轻松。

  下面便直接进入主题。

  我们知道一个函数是有作用域的,在函数内部定义的局部变量只有在函数内部才可以访问的到。一旦函数访问结束被销毁,局部变量随之也会销毁,无法通过任何方式再次访问局部变量,除了闭包。也就是说,我们可以通过闭包这一个方法,从函数的外部去访问到函数内部的变量,即使那个函数已经被销毁。没错,闭包最重要的用法就是,我们只提供某些接口去访问和修改局部变量,而外部是不能直接访问到局部变量的。

  说了那么多有关如何使用闭包,我们来看看闭包是长什么样子的。又到了举个栗子的环节,依然是最简单的people和name。

var people = function(){var name = "Yika";var sayName = function(){return name;  //访问了people函数的局部变量name
        }var setName = function(newName){name = newName;  //访问了people函数的局部变量name
        }return{sayName: sayName,setName: setName}//返回一个对象
    }var p1 = people();        //函数return的是一个对象,这个对象里有两个函数sayName和setNameconsole.log(p1.name);     //undefined.   name是people函数里的局部变量,而不是p1对象的属性,当然为undefinedconsole.log(p1.sayName());//"Yika"p1.setName("Ruyi");       //通过setName函数修改局部变量name的值console.log(p1.sayName());//"Ruyi"

  看完这个例子,想必对闭包多少有个了解啦,除了注释的内容,下面再做些补充。

  问:为什么局部变量name属性在people执行完之后,没有被销毁呢,反而数值还保存在内存中。

  答: 在例子中,函数注释那里专门写了(访问了people函数的局部变量name)。正是因为people函数里的sayName函数和setName函数访问了name属性,并且通过return传到了p1对象里,成了p1的两个方法。因为方法一直引用着people函数的局部变量,所以不会被消除,依然会在内存中。这样便形成了闭包,可以在函数外部访问到函数内部的局部变量。

  对此,我们可以换个更直观的写法。

var people = function(){var name = "Yika";var obj = {sayName: function(){return name;},setName: function(newName){name = newName}};return obj;       //直观的返回对象
    }
//下面的结果是一样的。

  当然闭包也不是一直那么好用,特别是在循环里。继续举例子

<body><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><script type="text/javascript">var oBtn = document.getElementsByTagName('input');for(var i = 0, len = oBtn.length; i < len; i++){oBtn[i].onclick = function(){alert("value = " + i);    //闭包陷阱的发生地!永远输出 value = 7
            }}</script>
</body>

  当我们运行上面的代码的时候,我们是这样想的,循环一下按钮,并输出按钮所在的序号,但是我们得到的却永远是7。其实用我们之前讲的闭包会让变量的值一直保存在内存中的原理想一想,就应该懂了。当我们循环的时候按钮的点击事件时,是引用了for循环里的 i 变量。当所有按钮都绑定了点击事件后,i 的值也已经变成了7,当然所有的按钮输出的都是7啦!怎么解决这个问题也很好办的,但是我希望留下给大家思考。这里就说一下大致思路吧,我们可以在循环之外创建一个辅助函数,并让辅助函数return一个绑定当前 i 的函数。

  当然这里我也只是抛砖引玉的介绍了一下闭包,希望可以帮到大家浅显简单的了解闭包。

  还是那句话噢,有问题立即指正,我一定会立马检查更正,以免误导了大家!

转载于:https://www.cnblogs.com/YikaJ/p/4040631.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jquery实现二级联动不与数据库交互

<select id"pro" name"pro" style"width:90px;"></select> <select id"city" name"city" style"width: 90px"></select> $._cityInfo [{"n":"北京市","c"…

[016]转--C++拷贝构造函数详解

一. 什么是拷贝构造函数 首先对于普通类型的对象来说&#xff0c;它们之间的复制是很简单的&#xff0c;例如&#xff1a; [c-sharp] view plaincopy int a 100; int b a; 而类对象与普通对象不同&#xff0c;类对象内部结构一般较为复杂&#xff0c;存在各种成员变量。下…

js中调用C标签实现百度地图

<script type"text/javascript"> //json数组 var jsonArray document.getElementById("restaurant").value; var map new BMap.Map("milkMap"); // 创建地图实例 <c:forEach items"${restaurantlist}" var"…

jquery较验组织机构编码

//*************************组织机构码较验************************* function checkOrganizationCode() { var weight [3, 7, 9, 10, 5, 8, 4, 2]; var str 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ; var reg /^([0-9A-Z]){8}-[0-9|X]{1}$/; var organizationcode $("…

自定义GrildView实现单选功能

首先看实现功能截图&#xff0c;这是一个自定义Dialog,并且里面内容由GrildView 绑定数据源&#xff0c;实现类似单选功能。 首先自定义Dialog&#xff0c;绑定数据源 自定义Dialog弹出框大小方法 最主要实现的就是点击颜色切换的功能&#xff0c;默认GrildView的每一项都是蓝色…

Java数字字符串如何转化为数字数组

eg&#xff1a; String numberString "0123456789"; 如何转化为&#xff1a;int[] digitArry new int[]{0,1,2,3,4,5,6,7,8,9}; 解决办法&#xff1a; char[] digitNumberArray numberString.toCharArray(); int[] digitArry new int[digitString.toCharArray().l…

『重构--改善既有代码的设计』读书笔记----序

作为C的程序员&#xff0c;我从大学就开始不间断的看书&#xff0c;看到如今上班&#xff0c;也始终坚持每天多多少少阅读技术文章&#xff0c;书看的很多&#xff0c;但很难有一本书&#xff0c;能让我去反复的翻阅。但唯独『重构--改善既有代码的设计』这本书让我重复看了不下…

微信公共平台接口开发--Java实现

Java微信实现&#xff0c;采用SpringMVC 架构&#xff0c;采用SAXReader解析XML RequestMapping(value"/extend") public class WeixinController { RequestMapping(value"/weixin") public ModelAndView weixin(HttpServletRequest request,HttpServlet…

最大权闭合图hdu3996

定义&#xff1a;最大权闭合图&#xff1a;是有向图的一个点集&#xff0c;且该点集的所有出边都指向该集合。即闭合图内任意点的集合也在改闭合图内&#xff0c;给每个点分配一个点权值Pu&#xff0c;最大权闭合图就是使闭合图的点权之和最大。 最小割建边方式&#xff1a;源点…

非监督学习的单层网络分析

这篇博客对应的是Andrew.Ng的那篇文章&#xff1a;An Analysis o f Single-Layer Networks in Unsupervised Feature Learning&#xff0c;文章的主要目的是讨论receptive field size&#xff0c;number of hidden nodes&#xff0c; step-stride以及whitening在对卷积网络模型…

Spring MVC 验证码

页面 <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <% String path request.getContextPath(); String basePath request.getScheme()"://"request.getServerName()":"request.getServerP…

数据结构实验之链表四:有序链表的归并

数据结构实验之链表四&#xff1a;有序链表的归并 Time Limit: 1000MS Memory limit: 65536K 题目描述 分别输入两个有序的整数序列&#xff08;分别包含M和N个数据&#xff09;&#xff0c;建立两个有序的单链表&#xff0c;将这两个有序单链表合并成为一个大的有序单链表&…

apk文件编译到系统文件中的方法(及包含so库的)

把第三方或自己开发的apk文件编译到系统文件(system.img)中的方法&#xff1a; 1 (1)源码编译后&#xff0c;把apk拷贝到out\target\product\generic\system\app中。 (2) 执行命令make snod , 把添加的spk编到system.img 中 缺点&#xff1a;执行make clean 后&#xff0c;再…

javascript中interval与setTimeOut的区别

setTimeout(code,millisec) //- 在指定时间后执行代码 code必须&#xff1b; millisec必须&#xff1b; clearTimeout(setTimeoutId) //- 取消 setTimeout() setInterval(code,millisec)&#xff1b;//指定间隔毫秒内循环执行代码 code必须&#xff1b; millisec必须&a…

java设计模式之单例模式(七种方法)

单例模式&#xff1a;个人认为这个是最简单的一种设计模式&#xff0c;而且也是在我们开发中最常用的一个设计模式。 单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例&#xff0c;而且自行实例化并向整个系统提供这个实例。这个类称为单例类。我们前面学习的…

java 遍历map集合

Map<String, String> map new HashMap<String, String>(); map.put("key1", "value1"); map.put("key2", "value2"); map.put("key3", "value3"); //第一种&#xff1a;通过Map.keySet遍…

poj3009 Curling 2.0 深搜

PS&#xff1a;以前看到题目这么长就没写下去了。今天做了半天&#xff0c;没做出来。准备看题解&#xff0c;打开了网站都忍住了&#xff0c;最后还是靠自己做出来的。算是一点进步吧。 分析&#xff1a; 题目的意思没明白或者理解有偏差都没办法做题。看样例3和样例4&#xf…

Android监听事件

ListView事件监听&#xff1a; setOnItemSelectedListener 鼠标滚动时触发 setOnItemClickListener 点击时触发 EditText事件监听&#xff1a; setOnKeyListener 获取焦点时触发 RadioGroup事件监听&#xff1a; setOnCheckedChangeListener 点击时触发 CheckBox事件监听&#…

子类能不能继承父类的构造方法?

class A{ public A(){} // 1:无参数构造方法。 public A(String s){} // 2.}class B extends A{ public B(String s){ super(s); // 3. }}说明&#xff1a;如果没有1处的无参数构造方法&#xff0c;那么3处一定要主动调用父类带参数的构造方法。如果有1处的构造方法&#…

基于原生javascript的ajax实现

function getXMLHttpRequest(){if(window.ActiveXObject){//用户是ie浏览器http_requestnew ActiveXObject("Microsoft.XMLHTTP");}else{//其他的浏览器http_requestnew XMLHttpRequest();}return http_request;}var httpRequest;function name(){httpRequestgetXMLH…