We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
维基百科中的概念
学术上
个人理解
案例分析是从浅入深希望大家都看完!
function A(){ var localVal=10; return localVal; } A();//输出30 function A(){ var localVal=10; return function(){ console.log(localVal); return localVal; } } var func=A(); func();//输出10
两段代码,在第二段代码中,函数A内的匿名函数可以访问到函数A中的局部变量这就是闭包的基本使用。
!function(){ var localData="localData here"; document.addEventListener('click',function(){ console.log(localData); }); }();
前端原始点击事件操作也用到了闭包来访问外部的局部变量。
!function(){ var localData="localData here"; var url="http://www.baidu.com"; $.ajax({ url:url, success:function(){ //do sth... console.log(localData); } }) }();
在ajax请求的方法中也用到了闭包,访问外部的局部变量。
var arrays = []; for (var i=0; i<3; i++) { arrays.push(function() { console.log('>>> ' + i); //all are 3 }); }
上面的这段代码,刚看了代码一定会以为陆续打印出1,2,3,实际输出的是3,3,3,出现这种情况的原因是匿名函数保存的是引用,当for循环结束的时候,i已经变成3了,所以打印的时候变成3。出现这种情况的解决办法是利用闭包解决问题。
for (var i=0; i<3; i++) { (function(n) { tasks.push(function() { console.log('>>> ' + n); }); })(i); }
闭包里的匿名函数,读取变量的顺序,先读取本地变量,再读取父函数的局部变量,如果找不到到全局里面搜索,i作为局部变量存到闭包里面,所以调整后的代码可以能正常打印1,2,3。
javascript的主要通过计数器方式回收内存,假设有a,b,c三个对象,当a引用b的时候,那么b的引用计算器增加1(通俗的说用到那个对象哪个对象引用计算器增加1),同时b引用c的时候,c引用计数器增加1,当a被释放的时候,b的引用计数器减少1,变成0的时候这个对象被释放,c计数器变成0,被释放,但是当遇到b和c之间互相引用的时候,无法通过计数器方式释放内存。
function A(){ var localVal=10; return function(){ console.log(localVal); return localVal; } } var func=A(); func();//输出10
当A函数结束的时候,想要释放,发现它的localVal变量被匿名函数引用,所有A函数无法释放,导致内存泄漏。但是也有好处,闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
说明:闭包不代表一定会带来内存泄漏,良好的使用闭包是不会造成内存泄漏的。
var person = function(){ //变量作用域为函数内部,外部无法访问 var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }(); print(person.name);//直接访问,结果为undefined print(person.getName()); person.setName("kaola"); print(person.getName()); 得到结果如下: undefined default kaola
doucument.body.innerHTML="<div id=div1>aaa</div>"+"<div id=div2>bbb</div>"+"<div id=div3>ccc</div>"; for(var i=1;i<4;i++){ !function(i){ document.getElementById('div'+i); addEventListener('click',function(){ alert(i);//1,2,3 }); } }
var CachedSearchBox = (function(){ var cache = {}, count = []; return { attachSearchBox : function(dsid){ if(dsid in cache){//如果结果在缓存中 return cache[dsid];//直接返回缓存中的对象 } var fsb = new uikit.webctrl.SearchBox(dsid);//新建 cache[dsid] = fsb;//更新缓存 if(count.length > 100){//保正缓存的大小<=100 delete cache[count.shift()]; } return fsb; }, clearSearchBox : function(dsid){ if(dsid in cache){ cache[dsid].clearSelection(); } } }; })(); CachedSearchBox.attachSearchBox("input");
说明:开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
闭包测试题: 求输出结果
function fun(n,o){ console.log(o); return { fun:function(m){//[2] return fun(m,n);//[1] } } } var a=fun(0); a.fun(1); a.fun(2); a.fun(3); var b=fun(0).fun(1).fun(2).fun(3); var c=fun(0).fun(1); c.fun(2); c.fun(3);
由于分析内容比较多,大家可直接参考这篇文章 https://cnodejs.org/topic/567ed16eaacb6923221de48f
分析内容说明,在看这篇文章的时候,注意两点可能会看的更明白:
The text was updated successfully, but these errors were encountered:
doucument.body.innerHTML="<div` id=div1>aaa</div>"+"<div id=div2>bbb</div>"+"<div id=div3>ccc</div>"; for(var i=1;i<4;i++){ !function(i){ document.getElementById('div'+i); addEventListener('click',function(){ alert(i);//1,2,3 }); } }
!、- 等符号是把匿名函数转化为表达式 ,那么在执行时应该加上'()' 比如
!function() { console.log('a') }()
Sorry, something went wrong.
文中还有例子有些小问题,
No branches or pull requests
什么是闭包
闭包的常见案例分析
案例分析是从浅入深希望大家都看完!
两段代码,在第二段代码中,函数A内的匿名函数可以访问到函数A中的局部变量这就是闭包的基本使用。
前端原始点击事件操作也用到了闭包来访问外部的局部变量。
在ajax请求的方法中也用到了闭包,访问外部的局部变量。
上面的这段代码,刚看了代码一定会以为陆续打印出1,2,3,实际输出的是3,3,3,出现这种情况的原因是匿名函数保存的是引用,当for循环结束的时候,i已经变成3了,所以打印的时候变成3。出现这种情况的解决办法是利用闭包解决问题。
闭包里的匿名函数,读取变量的顺序,先读取本地变量,再读取父函数的局部变量,如果找不到到全局里面搜索,i作为局部变量存到闭包里面,所以调整后的代码可以能正常打印1,2,3。
闭包与内存泄漏
javascript的主要通过计数器方式回收内存,假设有a,b,c三个对象,当a引用b的时候,那么b的引用计算器增加1(通俗的说用到那个对象哪个对象引用计算器增加1),同时b引用c的时候,c引用计数器增加1,当a被释放的时候,b的引用计数器减少1,变成0的时候这个对象被释放,c计数器变成0,被释放,但是当遇到b和c之间互相引用的时候,无法通过计数器方式释放内存。
第一个案例的代码拿过来分析:
当A函数结束的时候,想要释放,发现它的localVal变量被匿名函数引用,所有A函数无法释放,导致内存泄漏。但是也有好处,闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
说明:闭包不代表一定会带来内存泄漏,良好的使用闭包是不会造成内存泄漏的。
闭包的应用
说明:开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
面试题分析
闭包测试题: 求输出结果
由于分析内容比较多,大家可直接参考这篇文章
https://cnodejs.org/topic/567ed16eaacb6923221de48f
分析内容说明,在看这篇文章的时候,注意两点可能会看的更明白:
总结
The text was updated successfully, but these errors were encountered: