JavaScript之闭包
来源:互联网 发布:象棋软件开局库 编辑:程序博客网 时间:2024/05/17 09:21
一、闭包是什么?
闭包是可以访问独立变量的函数。因为函数是可以创造作用域的,函数的内部作用域是可以访问外部作用域,但是外部作用域是不能访问内部作用域的,所以在函数内声明的变量可以通过声明的内函数进行访问,然后把这个内函数返回,就可以在函数外面直接访问函数内的独立变量。
作用域链:就是函数可以创造作用域,在函数内部也可以声明函数,这就形成了作用域套作用域的链式结构,简称为作用域链。js分为内部作用域和外部作用域,访问变量都是从内向外沿着作用域链进行查找的。
二、闭包需要解决的问题是什么?
在函数外部访问函数内部声明的变量。
三、闭包的基本模式:
//1.基本模式: function outer(){ var data=10; function inner(){ return data; } return inner; } var fn=outer(); fn();//2.获取独立变量和设置独立变量: function outer(){ var data=10; function getData(){ return data; } function setData(value){ data=value; return data; } return { getData:getData, setData:setData }; } var fn=outer().setData; fn(100); //100 fn=outer().getData; fn(); //10//3.优化代码 function outer(){ var data=10; function inner(value){ if(value){ data=value; } return data; } return inner; } var fn=outer(); fn();
总结起来就是:返回一个函数,用这个函数获得数据;返回一个对象,这个对象包含函数,来操作这个数据
四、循环点击事件存在的问题及解决方案:
代码:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> div{ border:solid 1px #000; margin-bottom: 10px; width:70px; height:20px; } </style> <script> window.onload=function(){ var divs=document.getElementsByTagName("div"); for(var i=0;i<divs.length;i++){ var div=divs[i]; div.onclick=function(){ console.log("我是第"+i+"个div"); } } } </script></head><body> <div>第0个div</div> <div>第1个div</div> <div>第2个div</div> <div>第3个div</div> <div>第4个div</div> <div>第5个div</div> <div>第6个div</div></body></html>
期待的效果是:点击“第0个div”,显示“我是第0个div”,点击“第1个div”,显示“我是第1个div”。但是实际显示的是点击任何一个,显示的都是,“我是第7个div”。
//原因:因为在触发div点击onclick事件的时候,for循环已经执行完毕,这时候返回的i就是7,所以点击每一个div都是返回7
解决办法:使用闭包:将i变量保护起来
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> div{ border:solid 1px #000; margin-bottom: 10px; width:70px; height:20px; } </style> <script> window.onload=function(){ var divs=document.getElementsByTagName("div"); for(var i=0;i<divs.length;i++){ var div=divs[i]; function outer(){ var j=i; return function(){ console.log("我是第"+j+"个div"); } } div.onclick=outer(); //利用闭包解决了循环点击出现的问题 } } </script></head><body> <div>第0个div</div> <div>第1个div</div> <div>第2个div</div> <div>第3个div</div> <div>第4个div</div> <div>第5个div</div> <div>第6个div</div></body></html>
五、for循环中的setTimout出现的问题:
<script> for(var i=0;i<10;i++){ setTimeout(function(){ console.log(i); },0); } var a=10; alert(a);</script>
setTimout(function(){},time)是至少在time时间后执行回调函数。在js中有分主要任务和次要任务,主要任务就是主逻辑;次要任务就是setTimout和setInterval等回调函数。所以上述代码会先for循环,和setTimeout,执行下面的alert 10,再执行回调函数console.log(i),所以最终返回的也是10次10.
解决办法:利用闭包保护i变量:
<script> for(var i=0;i<10;i++){ function outer(){ var j=i; function inner(){ console.log(j); } return inner; } setTimeout(outer(),0); }</script>
六、斐波拉契数列的性能问题:
<script> //1. 用递归的方法实现斐波拉契数列: //增加count计数来计算每次fib函数执行的次数: //存在的问题:重复计算的次数太多, var count=0; function fib(n){ count++; if(n<=2){ return 1; }else{ return fib(n-1)+fib(n-2); } } fib(5); console.log(count); //9 count=0; fib(20); console.log(count); //13529 //2. 优化时间复杂度,可以使用非递归的方式实现斐波拉契数列: var count1=0; function fib1(n){ var a, b,res; a=b=1; if(n<=2){ return 1; }else{ for(var i=3;i<=n;i++){ count1++; res=a+b; a=b; b=res; } return res; } } fib1(20); //6765 console.log(count1); //18</script>
用递归实现的斐波拉契数列,就存在大量的重复计算,这种重复计算会导致count是成倍成指数型的增加,耗费计算机内存。
除了使用我上面代码中提到的用非递归的方式进行实现,还有一种方法也可以:就是将每次计算出来的fib(n)值存到数组里,这样如果有就直接取,没有就计算,计算好了就存;这样也是大大减少了重复计算量。
//3.利用数组存储的方式优化递归实现的斐波拉契数列算法: var arr=[]; var count2=0; function fib2(n){ count2++; var num=arr[n]; if(num){ return num; }else{ if(n<=2){ return 1; }else{ num=fib2(n-1)+fib2(n-2); arr[n]=num; return num; } } } fib2(20); //5 console.log(count2);
除此之外,这个arr变量暴露在全局,很可能被别人随意修改,我们可以通过闭包的方式保护这个变量:
//4.利用闭包优化递归实现的斐波拉契数列算法:(保护了数组变量arr) function fib3(){ var arr=[]; function fibIn(n){ var num=arr[n]; if(num){ return num; }else{ if(n<=2){ return 1; }else{ num=fib2(n-1)+fib2(n-2); arr[n]=num; return num; } } } return fibIn; } var fn=fib3(); fn(5);
七、Github源码地址:
https://github.com/spicyboiledfish/JavaScript-testJS
阅读全文
3 0
- javascript 之 闭包
- JavaScript之闭包
- JavaScript 之 闭包
- JavaScript之闭包
- javascript之闭包
- javascript之闭包
- javascript之闭包
- javascript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- Javascript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- JavaScript之闭包
- 基于NCBI的blast小程序
- JAVA复制文件或文件夹最快的方法
- httpServletRequest
- JavaScript中数据类型转换
- 利用Node.js与PDFKIT 生成PDF文件
- JavaScript之闭包
- springboot自学笔记
- OSCtxSw()
- Java 多线程
- ionic3/ag4编写模仿京东商城的demo
- Tensorflow教程-MNIST 数据下载
- vue安装
- NoSql
- iOS 自己封装的SDK 打包与合并,新手教程!!!