揭开JS闭包的面纱
今天看了关于js闭包方面的文章,还是有些云里雾里,对于一个菜鸟来说,学习闭包确实有一定的难度,不说别的,能够在网上找到一篇优秀的是那样的不易。
当然之所以闭包难理解,个人觉得是基础知识掌握的不牢,因为闭包牵扯到一些前面的东西,比如作用域\等等,如果连基本的作用域都没有弄清楚,自然不可能搞懂闭包,还有就是对js的实践比较少,因为你根本就不知道什么时候要用这东西,自然谈不上对闭包的深刻理解。
今天我就简单的说说我目前所理解的闭包,当然可能不完全正确,但是我相信会给你一定的启发。
首先我们来谈谈js中的变量,如果你不知道我为什么要说这些,那么你根本没有掌握js的基础,建议回头复习。
js中分:全局变量 和 局部变量
全局变量:可以在任意位置访问的量就叫全局变量
1 var age = 20;
2 function a(){
3 console.log(age); >>20
4 }
5 a();
局部变量:函数中用var定义的变量,只能在函数中访问这个变量,函数外部访问不了。
1 function a(){
2 var age = 20;
3 }
4 a();
5 console.log(age); >> Uncaught ReferenceError: age is not defined
注意点1:在函数中如果不使用var定义变量那么js引擎会自动添加成全局变量。
注意点2:全局变量从创建的那一刻起就会一直保存在内存中,除非你关闭这个页面,局部变量当函数运行完以后就会销毁这个变量,假如有多次调用这个函数它下一次调用的时候又会重新创建那个变量,既运行完就销毁,回到最初的状态,简单来说局部变量是一次性的,用完就扔,下次要我再重新创建。
函数的相关知识点:
1. 一个函数内可以嵌套多个函数
2. 函数里面的子函数可以访问它上级定义的变量,注意不只是一级,如果上级没有会继续往上级找,直到找到为止,如果找到全局变量到找不到就会报错。

1 function a(){
2 var name = "追梦子";
3 function b(){
4 console.log(name); >> "追梦子"
5 }
6 b();
7 }
8 a();

3. 函数的另外一种调用形式,你可以把它叫做自调用,自己调用自己,达到自执行的效果。
1 var a = 0;
2 (function(){
3 console.log(++a); >>1
4 })()
这种方式用()把内容包裹起来,后面的()表示执行这个函数,可能你会问为什么要把函数包起来,如果不包裹起来,js会把它当作函数声明来处理,如果包裹起来就是表达式,还没有看懂就上网查吧。
开始我们正式闭包部分---------------------------- 币包 ---------------像钱包一样的东西,可以把东西包裹起来----------
首先我们来看看为什么需要学习闭包,加以理解 -- 0 v 0- -
1 function a(){
2 var num = 0;
3 console.log(++num);
4 }
5 a(); >>1
6 a(); >>1
上面代码输出了两次1,为什么呢?如果你有看我上面的关于变量部分肯定能够想到个大概。
前面我们说过了函数执行完以后,里面的变量(即局部变量)就会销毁,下一次运行又会重新创建那个变量,所以虽然你第一次++num了但是这个变量在第一次执行完毕以后就被销毁了。
那么我们怎么样才能确保第一次的变量不被销毁,那么就需要我们的闭包出场了。
温馨提示:JavaScript中有回收机制,函数没有被引用执行完以后这个函数的作用域就会被销毁,如果一个函数被其他变量引用,这个函数的作用域将不会被销毁,(简单来说就是函数里面的变量会被保存下来,你可以理解成全局变量。)
…………………………………………………………………………………… 当 当 当 ................. 下面有请我们的币包同志

function a(){
var aa = ;
function b(){
aa ++;
console.log(aa);
}
return b;
}
var ab = a();
ab(); //1
ab(); //2

看到了吧里面的变量的值没有被销毁,因为函数a被外部的变量ab引用,所以变量aa没有被回收。
如果某个函数被它的父函数之外的一个变量引用,就形成了一个闭包
还有一种更为常用的闭包写法

var bi = (function(){
var a = ;
function b(){
a ++;
console.log(a);
}
return b;
})();
bi(); //1
bi(); //2
bi(); //3

执行过程分析:
首先把一个自执行函数赋值给了bi,这个自执行函数运行完成以后就bi的值就变成了
function b(){
a ++;
console.log(a);
}
因为我们在上面的代码return回去了b,然后因为这个自执行函数被bi引用所以里面的变量a并没有因为这个自执行函数执完而销毁,而是保存到了内存中,所以我们多次打印bi()就成了1、2、3
下面我来说一个闭包的使用场景吧。
没有使用闭包的版本

window.onload = function(){
var ul = document.getElementsByTagName("ul")[0];
var li = ul.getElementsByTagName("li");
for(var i=0;i<li.length;i++){
li[i].onclick = function(){
console.log(i); //不管我怎么点都是返回
}
}
}

使用了闭包的版本

window.onload = function(){
var ul = document.getElementsByTagName("ul")[0];
var li = ul.getElementsByTagName("li");
for(var i=0;i<li.length;i++){
(function(i){
li[i].onclick = function(){
console.log(i); //点击第几个返回第几个
}
})(i)
}
}

、、、、、如果你不理解这个,你只要这样子用就能够达到效果。
揭开JS闭包的面纱的更多相关文章
- js闭包的作用域以及闭包案列的介绍:
转载▼ 标签: it js闭包的作用域以及闭包案列的介绍: 首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ...
- 大部分人都会做错的经典JS闭包面试题
由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) ...
- Js闭包常见三种用法
Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...
- ASP.NET 运行时详解 揭开请求过程神秘面纱
对于ASP.NET开发,排在前五的话题离不开请求生命周期.像什么Cache.身份认证.Role管理.Routing映射,微软到底在请求过程中干了哪些隐秘的事,现在是时候揭晓了.抛开乌云见晴天,接下来就 ...
- js闭包之初步理解( JavaScript closure)
闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...
- (原创)JS闭包看代码理解
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- js闭包理解
js闭包的作用是使函数外可以访问函数内部的变量,是通过 在函数内部 定义 访问函数内变量 的函数实现的,内部的一个函数产生一个闭包 function a() { var i=0; return fun ...
- 带你揭开ATM的神秘面纱
相信大家都用过ATM取过money吧,但是有多少人真正是了解ATM的呢?相信除了ATM从业者外了解的人寥寥无几吧,鄙人作为一个从事ATM软件开发的伪专业人士就站在我的角度为大家揭开ATM的神秘面纱吧. ...
- js闭包理解实例小结
Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 <script type="text/javascript"> ...
随机推荐
- CodeForces 868F Yet Another Minimization Problem(决策单调性优化 + 分治)
题意 给定一个序列 \(\{a_1, a_2, \cdots, a_n\}\),要把它分成恰好 \(k\) 个连续子序列. 每个连续子序列的费用是其中相同元素的对数,求所有划分中的费用之和的最小值. ...
- 川普和习G-20会面为缓和中美贸易战提供了很大的机会
川普和习将于这周在Buenos Aires(阿根廷首都)会面,互相商讨虚弱经济全球化的最大威胁. 自从川普在今年七月第一次开始提高中国商品关税之后,对全球的投资者和逐渐削弱的经济活动来说,两位领导人可 ...
- GWAS群体分层 (Population stratification):利用plink对基因型进行PCA
一.为什么要做祖先成分的PCA? GWAS研究时经常碰到群体分层的现象,即该群体的祖先来源多样性,我们知道的,不同群体SNP频率不一样,导致后面做关联分析的时候可能出现假阳性位点(不一定是显著信号位点 ...
- Subversion配置
1.下载Apache-Subversion-1.9.7:https://github.com/wangfajun/dev-tools 2.打开idea-->File-->Settings, ...
- IE提示“Internet Explorer已限制此网页运行脚本或ActiveX控件”的解决办法
在页面html开始标签和head开始标签中间新增一行,添加以下代码: <!-- saved from url=(0014)about:internet --> 或者 直接设置IE浏览器 工 ...
- python3中的socket
socket是什么?用它做什么? socket,我们通俗的称之为套接字, 是进程间通信的一种方式,但是他与其他进程通信的一个主要区别是 他能实现不同主机间的通信,比如我们现在用的浏览器,在比如我们使用 ...
- Hello jna
记录下这几天用jna3.5.0调c++写的dll的经历 os:win7 用jna调dll首先需要一个dll文件并有可调的方法,然后根据方法的名称,参数,返回值编写一个interface c++需要包含 ...
- 408 JavaScript 变量、数据类型、正则
JavaScript 特点 是一门解释性脚本语言 .基于对象脚本编程.简单性(弱类型).安全性.动态性.跨平台 作用: 初学js 引入方式 与html有相同之处 也是3种1 用JavaScript前缀 ...
- day03 数据类型与运算符
今日内容: 1.变量及常量的命名规范 2.与用户的交互 3.字符串的格式化输出 4.基本的数据类型 5.运算符 6.注释 今日重点: 1.变量及常量的命名规范 (1)强制规范[如果违反会报错] 1&g ...
- Spring注解@Configuration和Java Config
1.从Spring 3起,JavaConfig功能已经包含在Spring核心模块,它允许开发者将bean定义和在Spring配置XML文件到Java类中.但是,仍然允许使用经典的XML方式来定义bea ...