关于javascript闭包的理解
来源:互联网 发布:vb.net 控件数组 编辑:程序博客网 时间:2024/06/05 11:23
一:从概念上理解:
1.闭包的定义:
有权访问另一个访问另一个函数作用域中变量的函数。
2.实现方式:
在函数内部创建另一个函数。结合定义举例:b函数为了访问a函数的作用域中的变量:我们就将b函数创建在a函数当中。当然b函数通常是匿名函数的。
二:理解闭包的前提-----理解作用域链以及执行环境:
1.当一个函数被调用时候,会创建一个执行环境(每个执行环境都有一个表示变量的对象-----变量对象)以及相应的作用域链。内部函数可以访问外部函数的作用域,查找时候由内而外直到全局变量。
ex:
var m = 3;function plus(a,b){ return a+b+m;} var c = plus(1,2 ); // 6
以上代码先定义了plus函数,再在全局作用域中调用,根据其作用域链,plus是可以访问到全局作用域中的m的。调用plus时候会创建一个包含a,b以及arguments的变量对象(是个活动对象,函数执行完毕被销毁),而全局执行环境的变量对象始终存在。而闭包的情况下,情况又有所不同。
因就在于f1是f2的父函数,而f2被赋给了一个全局变量result,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
阮一峰的这个例子还是埋了一个坑的:这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
前端小白,欢迎拍砖。
三.闭包举例的以及其作用
1.访问函数的内部变量
function f1(){ var n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999为了在全局作用域中访问到f1作用域中的n,将n在f1内部函数f2中返回。其实通常情况下不会向上面那样写,f2会作为一个匿名函数返回像下面这样:
return function(){ return n}2.让这些变量一直保存在内存中:
function f1(){ var n=999; nAdd=function(){n+=1} return function (){ alert(n); } } var result=f1(); result(); // 999 nAdd(); result(); // 1000可以看到第一次访问到了f1的内部变量,所以值为999,执行nAdd()后n的值为1000,并且函数执行完毕没有被销毁,所以再次执行f1,会得到n=1000;why?
因就在于f1是f2的父函数,而f2被赋给了一个全局变量result,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
阮一峰的这个例子还是埋了一个坑的:这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
闭包引起的问题:
1.闭包使得其父函数的变量也会保存在内存中,如果不手动释放会一直占用内存。上例子的释放:
result = null;实际上是解除了对匿名函数的引用。
2.对父函数中值得改变:
上例子中n值的改变。
理解闭包的经典的例子:
一:
var name = "outer"; var object = { name : "inner", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());关键点;this的指向是基于调用它的执行环境绑定的。所以结果是:outer。
var name = "outer"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());关键点:首先将this赋给了一个成员变量that,因此,函数调用的作用域就限制在了obj对象中,其他的如前面代码段1的分析,最后结果输出的是"inner"
二:
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000);}
结果是:10个10.而不是预期 的1-10.即使是把时间设置成0也是一样。可以理解成异步执行。
先给一个比较容易接受的解释:作用域链的配置机制引起的问题:闭包只能取得包含函数中任何变量的最后一个值;闭包保存的是整个的变量对象而不是某个值。再来换一个解释:因为setTimeout中的匿名function没有将 i 作为参数传入来固定这个变量的值, 让其保留下来, 而是直接引用了外部作用域中的 i。.
如何得到1-10?
for (var i = 0; i < 10; i++) { (function(a) { // 变量 i 的值在传递到这个作用域时被复制给了 a, // 因此这个值就不会随外部变量而变化了 setTimeout(function() { console.log(a); }, 1000); })(i); // 我们在这里传入参数来"闭包"变量 }
前端小白,欢迎拍砖。
1 0
- 关于Javascript闭包的理解
- 关于 Javascript 的闭包理解
- 关于JavaScript闭包的理解
- 关于javascript闭包的理解
- Javascript初学者关于对闭包的理解
- 一些关于javascript闭包和this的理解
- 理解javascript的闭包
- 理解Javascript的闭包
- 理解Javascript的闭包
- 理解Javascript的闭包
- 理解Javascript的闭包
- Javascript的闭包理解
- 理解Javascript的闭包
- javascript 闭包的理解
- 理解Javascript的闭包
- Javascript闭包的理解
- 理解Javascript的闭包
- 理解Javascript的闭包
- 【网络编程】Trojan源码 文件传输+远程cmd+键盘记录
- 重磅!神经网络浅讲:从神经元到深度学习
- 工作流学习——重要概念扫盲篇一步曲
- 关于寻路算法的一些思考(3):A*算法的实现
- 什么是死锁
- 关于javascript闭包的理解
- 看过这两张图,就明白 Buffer 和 Cache 之间区别
- vlc 做rtp、rtsp调试
- Python 面试题(全面)
- Visual Studio控制台程序输出窗口一闪而过的解决方法
- Android主流网络请求开源库的对比(Android-Async-Http、Volley、OkHttp、Retrofit)
- java单例模式 原子类 线程安全
- 魔法少女
- android布局属性