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 = 0;
function b(){
aa ++;
console.log(aa);
}
return b;
}
var ab = a();
ab(); //1
ab(); //2

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

var bi = (function(){
var a = 0;
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); //不管我怎么点都是返回6
}
}
}

使用了闭包的版本

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)
}
}

、、、、、如果你不理解这个,你只要这样子用就能够达到效果。
这也只是简单的介绍了一下,后面将会在闭包的高级部分讲解。如果你对闭包有更深的理解可以pm我。
js 的闭包的更多相关文章
- 关于js中闭包的理解
1.以前很不理解js中闭包的概念及使用,下面来看一下 function foo() { var a = 123; var b = 456; return function () { return a; ...
- js的闭包
一,关于js闭包的只是感觉很高大上似乎,对于学弱来说任何问题都是这样的,值得去钻研和提高. 资料上理解的都是关于js的闭包其实就是js的变量的作用域的灵活使用. 函数内部定义变量的时候,一定要用 va ...
- 彻底搞清js中闭包(Closure)的概念
js中闭包这个概念对于初学js的同学来说, 会比较陌生, 有些难以理解, 理解起来非常模糊. 今天就和大家一起来探讨一下这个玩意. 相信大家在看完后, 心中的迷惑会迎然而解. 闭包概念: 闭包就是有权 ...
- 理解运用JS的闭包、高阶函数、柯里化
JS的闭包,是一个谈论得比较多的话题了,不过细细想来,有些人还是理不清闭包的概念定义以及相关的特性. 这里就整理一些,做个总结. 一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执 ...
- JS的闭包、高阶函数、柯里化
本文原链接:https://cloud.tencent.com/developer/article/1326958 https://cloud.tencent.com/developer/articl ...
- 关于js的闭包和复制对象
一.有关js的闭包 1.概念:所谓的闭包,就是指的两个作用域,其中内层作用于可以访问外层作用域的函数的现象 2.简单应用 for(var i = 0;i< lis.lenth;i++){ (fu ...
- JS的闭包问题
1.什么是“闭包” 是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 2.闭包的应用场景 (1)保护变量的安全实现JS私有属性和私有方法 (2)在 ...
- 深入理解JS的闭包
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...
- js的闭包概念
一.变量的作用域要懂得闭包,起首必须懂得Javascript特别的变量作用域.变量的作用域无非就是两种:全局变量和局部变量.Javascript说话的特别之处,就在于函数内部可以直接读取全局变量. J ...
随机推荐
- 关于Autoit上传文件的问题
Autoit上传文件需要安装两个软件: 使用这个做文件上传时:在代码中需要添加的代码如下: Runtime.getRuntime().exec("d:/zhpg.exe"); D盘 ...
- SpringMVC——接收请求参数和页面传参
Spring接收请求参数: 1.使用HttpServletRequest获取 @RequestMapping("/login.do") public String login(Ht ...
- 接口(Java)
什么是接口:接口就是一些方法特征的集合,接口是对抽象的抽象. 在java语言中,接口有两种意思: ①概念性的接口,即系统对外提供的所有服务 ②指用interface关键字定义的接口,也称为接口类型 特 ...
- HDU1892二维树状数组
See you~ Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Su ...
- NVelocity+Bootstrap tab控件 异常之
异常信息:Encountered "tings" at line 54, column 55.Was expecting one of: "(" ... ...
- Spring的quartz定时器同一时刻重复执行二次的问题解决
最近用Spring的quartz定时器的时候,发现到时间后,任务总是重复执行两次,在tomcat或jboss下都如此. 打印出他们的hashcode,发现是不一样的,也就是说,在web容器启动的时候, ...
- 数组API
1.数组的创建 var arrayObj = new Array();//创建一个默认数组,长度是0 var arrayObj = new Array(size);//创建一个size长度的数组,注意 ...
- 关于c++风格 code style
Header files should be self-contained. All header files should have #define guards to prevent multip ...
- JS写的CRC16校验算法(查表法)
var CRC = {}; CRC._auchCRCHi = [ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0 ...
- Flink - Checkpoint
Flink在流上最大的特点,就是引入全局snapshot, CheckpointCoordinator 做snapshot的核心组件为, CheckpointCoordinator /** * T ...